Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
authorJohn W. Linville <linville@tuxdriver.com>
Mon, 19 Dec 2011 18:54:26 +0000 (13:54 -0500)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 19 Dec 2011 18:54:26 +0000 (13:54 -0500)
168 files changed:
drivers/bcma/bcma_private.h
drivers/bcma/host_pci.c
drivers/bcma/main.c
drivers/bcma/sprom.c
drivers/net/wireless/ath/ath.h
drivers/net/wireless/ath/ath9k/Kconfig
drivers/net/wireless/ath/ath9k/Makefile
drivers/net/wireless/ath/ath9k/ar9003_mac.c
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/debug.c
drivers/net/wireless/ath/ath9k/debug.h
drivers/net/wireless/ath/ath9k/dfs.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k/dfs.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k/dfs_debug.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k/dfs_debug.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k/hw-ops.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/mci.c
drivers/net/wireless/ath/ath9k/mci.h
drivers/net/wireless/ath/ath9k/rc.c
drivers/net/wireless/ath/ath9k/recv.c
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/ath/regd.c
drivers/net/wireless/b43/phy_n.c
drivers/net/wireless/b43/phy_n.h
drivers/net/wireless/b43/radio_2056.c
drivers/net/wireless/b43/radio_2056.h
drivers/net/wireless/b43/tables_nphy.c
drivers/net/wireless/b43/tables_nphy.h
drivers/net/wireless/brcm80211/Kconfig
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
drivers/net/wireless/brcm80211/brcmfmac/dhd.h
drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c
drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
drivers/net/wireless/brcm80211/brcmsmac/aiutils.c
drivers/net/wireless/brcm80211/brcmsmac/aiutils.h
drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
drivers/net/wireless/brcm80211/brcmsmac/d11.h
drivers/net/wireless/brcm80211/brcmsmac/dma.c
drivers/net/wireless/brcm80211/brcmsmac/dma.h
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h
drivers/net/wireless/brcm80211/brcmsmac/main.c
drivers/net/wireless/brcm80211/brcmsmac/main.h
drivers/net/wireless/brcm80211/brcmsmac/nicpci.c
drivers/net/wireless/brcm80211/brcmsmac/nicpci.h
drivers/net/wireless/brcm80211/brcmsmac/otp.c
drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c
drivers/net/wireless/brcm80211/brcmsmac/phy/phy_hal.h
drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h
drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c
drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c
drivers/net/wireless/brcm80211/brcmsmac/pmu.c
drivers/net/wireless/brcm80211/brcmsmac/pmu.h
drivers/net/wireless/brcm80211/brcmsmac/pub.h
drivers/net/wireless/brcm80211/brcmsmac/srom.c
drivers/net/wireless/brcm80211/brcmsmac/srom.h
drivers/net/wireless/brcm80211/brcmsmac/types.h
drivers/net/wireless/brcm80211/include/chipcommon.h
drivers/net/wireless/iwlwifi/Kconfig
drivers/net/wireless/iwlwifi/Makefile
drivers/net/wireless/iwlwifi/iwl-5000.c
drivers/net/wireless/iwlwifi/iwl-6000.c
drivers/net/wireless/iwlwifi/iwl-agn-calib.c
drivers/net/wireless/iwlwifi/iwl-agn-calib.h
drivers/net/wireless/iwlwifi/iwl-agn-lib.c
drivers/net/wireless/iwlwifi/iwl-agn-rs.c
drivers/net/wireless/iwlwifi/iwl-agn-rs.h
drivers/net/wireless/iwlwifi/iwl-agn-rx.c
drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
drivers/net/wireless/iwlwifi/iwl-agn-sta.c
drivers/net/wireless/iwlwifi/iwl-agn-tx.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-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-mac80211.c
drivers/net/wireless/iwlwifi/iwl-shared.h
drivers/net/wireless/iwlwifi/iwl-testmode.c
drivers/net/wireless/iwlwifi/iwl-testmode.h
drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
drivers/net/wireless/iwlwifi/iwl-trans.h
drivers/net/wireless/iwlwifi/iwl-ucode.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/mwifiex/cfg80211.c
drivers/net/wireless/mwifiex/cfg80211.h
drivers/net/wireless/mwifiex/cmdevt.c
drivers/net/wireless/mwifiex/init.c
drivers/net/wireless/mwifiex/main.c
drivers/net/wireless/mwifiex/main.h
drivers/net/wireless/mwifiex/pcie.c
drivers/net/wireless/mwifiex/scan.c
drivers/net/wireless/mwifiex/sdio.c
drivers/net/wireless/mwifiex/sta_event.c
drivers/net/wireless/mwifiex/sta_ioctl.c
drivers/net/wireless/mwifiex/txrx.c
drivers/net/wireless/rt2x00/rt2x00mac.c
drivers/net/wireless/rtlwifi/base.c
drivers/net/wireless/rtlwifi/pci.c
drivers/net/wireless/rtlwifi/ps.c
drivers/net/wireless/rtlwifi/wifi.h
drivers/net/wireless/wl12xx/acx.c
drivers/net/wireless/wl12xx/acx.h
drivers/net/wireless/wl12xx/debugfs.c
drivers/net/wireless/wl12xx/init.c
drivers/net/wireless/wl12xx/init.h
drivers/net/wireless/wl12xx/main.c
drivers/net/wireless/wl12xx/rx.c
drivers/net/wireless/wl12xx/testmode.c
drivers/net/wireless/wl12xx/tx.c
drivers/net/wireless/wl12xx/wl12xx.h
drivers/nfc/pn533.c
drivers/ssb/pci.c
include/linux/bcma/bcma.h
include/linux/bcma/bcma_driver_chipcommon.h
include/linux/ieee80211.h
include/linux/nfc.h
include/linux/nl80211.h
include/linux/ssb/ssb.h
include/linux/ssb/ssb_regs.h
include/net/cfg80211.h
include/net/nfc/nfc.h
net/mac80211/agg-tx.c
net/mac80211/cfg.c
net/mac80211/debugfs_netdev.c
net/mac80211/ht.c
net/mac80211/ibss.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/main.c
net/mac80211/mesh_plink.c
net/mac80211/mlme.c
net/mac80211/rx.c
net/mac80211/sta_info.c
net/mac80211/sta_info.h
net/mac80211/status.c
net/mac80211/tx.c
net/mac80211/util.c
net/nfc/Kconfig
net/nfc/Makefile
net/nfc/core.c
net/nfc/llcp/Kconfig [new file with mode: 0644]
net/nfc/llcp/commands.c [new file with mode: 0644]
net/nfc/llcp/llcp.c [new file with mode: 0644]
net/nfc/llcp/llcp.h [new file with mode: 0644]
net/nfc/llcp/sock.c [new file with mode: 0644]
net/nfc/nci/core.c
net/nfc/nci/data.c
net/nfc/nci/ntf.c
net/nfc/nci/rsp.c
net/nfc/netlink.c
net/nfc/nfc.h
net/nfc/rawsock.c
net/wireless/core.h
net/wireless/nl80211.c
net/wireless/reg.c
net/wireless/sme.c
net/wireless/util.c

index 30a3085d3354577d68e3121e4dfb77c57cc4409f..fda56bde36b836cc7fa4a8bee2c1bc92b0e5a43d 100644 (file)
@@ -18,6 +18,9 @@ void bcma_bus_unregister(struct bcma_bus *bus);
 int __init bcma_bus_early_register(struct bcma_bus *bus,
                                   struct bcma_device *core_cc,
                                   struct bcma_device *core_mips);
+#ifdef CONFIG_PM
+int bcma_bus_resume(struct bcma_bus *bus);
+#endif
 
 /* scan.c */
 int bcma_bus_scan(struct bcma_bus *bus);
index b0994c0e05dc9642c0d878ed3bb03021d876e14e..443b83a2fd7aa012c1c6835137e2642a79499b41 100644 (file)
@@ -234,6 +234,41 @@ static void bcma_host_pci_remove(struct pci_dev *dev)
        pci_set_drvdata(dev, NULL);
 }
 
+#ifdef CONFIG_PM
+static int bcma_host_pci_suspend(struct pci_dev *dev, pm_message_t state)
+{
+       /* Host specific */
+       pci_save_state(dev);
+       pci_disable_device(dev);
+       pci_set_power_state(dev, pci_choose_state(dev, state));
+
+       return 0;
+}
+
+static int bcma_host_pci_resume(struct pci_dev *dev)
+{
+       struct bcma_bus *bus = pci_get_drvdata(dev);
+       int err;
+
+       /* Host specific */
+       pci_set_power_state(dev, 0);
+       err = pci_enable_device(dev);
+       if (err)
+               return err;
+       pci_restore_state(dev);
+
+       /* Bus specific */
+       err = bcma_bus_resume(bus);
+       if (err)
+               return err;
+
+       return 0;
+}
+#else /* CONFIG_PM */
+# define bcma_host_pci_suspend NULL
+# define bcma_host_pci_resume  NULL
+#endif /* CONFIG_PM */
+
 static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = {
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) },
@@ -249,6 +284,8 @@ static struct pci_driver bcma_pci_bridge_driver = {
        .id_table = bcma_pci_bridge_tbl,
        .probe = bcma_host_pci_probe,
        .remove = bcma_host_pci_remove,
+       .suspend = bcma_host_pci_suspend,
+       .resume = bcma_host_pci_resume,
 };
 
 int __init bcma_host_pci_init(void)
index 70c84b95109860205a7ec1d216ef8df58f34ba30..10f92b371e582bf6d371f425b17dd1dfe5629afd 100644 (file)
@@ -240,6 +240,22 @@ int __init bcma_bus_early_register(struct bcma_bus *bus,
        return 0;
 }
 
+#ifdef CONFIG_PM
+int bcma_bus_resume(struct bcma_bus *bus)
+{
+       struct bcma_device *core;
+
+       /* Init CC core */
+       core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
+       if (core) {
+               bus->drv_cc.setup_done = false;
+               bcma_core_chipcommon_init(&bus->drv_cc);
+       }
+
+       return 0;
+}
+#endif
+
 int __bcma_driver_register(struct bcma_driver *drv, struct module *owner)
 {
        drv->drv.name = drv->name;
index d7292390d236dddf8a8979bf313d904762c76d70..6f230fb087c5ebd064a52aafa8924368b2039c0e 100644 (file)
@@ -129,6 +129,9 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
        u16 v;
        int i;
 
+       bus->sprom.revision = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] &
+               SSB_SPROM_REVISION_REV;
+
        for (i = 0; i < 3; i++) {
                v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i];
                *(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v);
@@ -136,12 +139,70 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
 
        bus->sprom.board_rev = sprom[SPOFF(SSB_SPROM8_BOARDREV)];
 
+       bus->sprom.txpid2g[0] = (sprom[SPOFF(SSB_SPROM4_TXPID2G01)] &
+            SSB_SPROM4_TXPID2G0) >> SSB_SPROM4_TXPID2G0_SHIFT;
+       bus->sprom.txpid2g[1] = (sprom[SPOFF(SSB_SPROM4_TXPID2G01)] &
+            SSB_SPROM4_TXPID2G1) >> SSB_SPROM4_TXPID2G1_SHIFT;
+       bus->sprom.txpid2g[2] = (sprom[SPOFF(SSB_SPROM4_TXPID2G23)] &
+            SSB_SPROM4_TXPID2G2) >> SSB_SPROM4_TXPID2G2_SHIFT;
+       bus->sprom.txpid2g[3] = (sprom[SPOFF(SSB_SPROM4_TXPID2G23)] &
+            SSB_SPROM4_TXPID2G3) >> SSB_SPROM4_TXPID2G3_SHIFT;
+
+       bus->sprom.txpid5gl[0] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL01)] &
+            SSB_SPROM4_TXPID5GL0) >> SSB_SPROM4_TXPID5GL0_SHIFT;
+       bus->sprom.txpid5gl[1] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL01)] &
+            SSB_SPROM4_TXPID5GL1) >> SSB_SPROM4_TXPID5GL1_SHIFT;
+       bus->sprom.txpid5gl[2] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL23)] &
+            SSB_SPROM4_TXPID5GL2) >> SSB_SPROM4_TXPID5GL2_SHIFT;
+       bus->sprom.txpid5gl[3] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL23)] &
+            SSB_SPROM4_TXPID5GL3) >> SSB_SPROM4_TXPID5GL3_SHIFT;
+
+       bus->sprom.txpid5g[0] = (sprom[SPOFF(SSB_SPROM4_TXPID5G01)] &
+            SSB_SPROM4_TXPID5G0) >> SSB_SPROM4_TXPID5G0_SHIFT;
+       bus->sprom.txpid5g[1] = (sprom[SPOFF(SSB_SPROM4_TXPID5G01)] &
+            SSB_SPROM4_TXPID5G1) >> SSB_SPROM4_TXPID5G1_SHIFT;
+       bus->sprom.txpid5g[2] = (sprom[SPOFF(SSB_SPROM4_TXPID5G23)] &
+            SSB_SPROM4_TXPID5G2) >> SSB_SPROM4_TXPID5G2_SHIFT;
+       bus->sprom.txpid5g[3] = (sprom[SPOFF(SSB_SPROM4_TXPID5G23)] &
+            SSB_SPROM4_TXPID5G3) >> SSB_SPROM4_TXPID5G3_SHIFT;
+
+       bus->sprom.txpid5gh[0] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH01)] &
+            SSB_SPROM4_TXPID5GH0) >> SSB_SPROM4_TXPID5GH0_SHIFT;
+       bus->sprom.txpid5gh[1] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH01)] &
+            SSB_SPROM4_TXPID5GH1) >> SSB_SPROM4_TXPID5GH1_SHIFT;
+       bus->sprom.txpid5gh[2] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH23)] &
+            SSB_SPROM4_TXPID5GH2) >> SSB_SPROM4_TXPID5GH2_SHIFT;
+       bus->sprom.txpid5gh[3] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH23)] &
+            SSB_SPROM4_TXPID5GH3) >> SSB_SPROM4_TXPID5GH3_SHIFT;
+
        bus->sprom.boardflags_lo = sprom[SPOFF(SSB_SPROM8_BFLLO)];
        bus->sprom.boardflags_hi = sprom[SPOFF(SSB_SPROM8_BFLHI)];
        bus->sprom.boardflags2_lo = sprom[SPOFF(SSB_SPROM8_BFL2LO)];
        bus->sprom.boardflags2_hi = sprom[SPOFF(SSB_SPROM8_BFL2HI)];
 
        bus->sprom.country_code = sprom[SPOFF(SSB_SPROM8_CCODE)];
+
+       bus->sprom.fem.ghz2.tssipos = (sprom[SPOFF(SSB_SPROM8_FEM2G)] &
+               SSB_SROM8_FEM_TSSIPOS) >> SSB_SROM8_FEM_TSSIPOS_SHIFT;
+       bus->sprom.fem.ghz2.extpa_gain = (sprom[SPOFF(SSB_SPROM8_FEM2G)] &
+               SSB_SROM8_FEM_EXTPA_GAIN) >> SSB_SROM8_FEM_EXTPA_GAIN_SHIFT;
+       bus->sprom.fem.ghz2.pdet_range = (sprom[SPOFF(SSB_SPROM8_FEM2G)] &
+               SSB_SROM8_FEM_PDET_RANGE) >> SSB_SROM8_FEM_PDET_RANGE_SHIFT;
+       bus->sprom.fem.ghz2.tr_iso = (sprom[SPOFF(SSB_SPROM8_FEM2G)] &
+               SSB_SROM8_FEM_TR_ISO) >> SSB_SROM8_FEM_TR_ISO_SHIFT;
+       bus->sprom.fem.ghz2.antswlut = (sprom[SPOFF(SSB_SPROM8_FEM2G)] &
+               SSB_SROM8_FEM_ANTSWLUT) >> SSB_SROM8_FEM_ANTSWLUT_SHIFT;
+
+       bus->sprom.fem.ghz5.tssipos = (sprom[SPOFF(SSB_SPROM8_FEM5G)] &
+               SSB_SROM8_FEM_TSSIPOS) >> SSB_SROM8_FEM_TSSIPOS_SHIFT;
+       bus->sprom.fem.ghz5.extpa_gain = (sprom[SPOFF(SSB_SPROM8_FEM5G)] &
+               SSB_SROM8_FEM_EXTPA_GAIN) >> SSB_SROM8_FEM_EXTPA_GAIN_SHIFT;
+       bus->sprom.fem.ghz5.pdet_range = (sprom[SPOFF(SSB_SPROM8_FEM5G)] &
+               SSB_SROM8_FEM_PDET_RANGE) >> SSB_SROM8_FEM_PDET_RANGE_SHIFT;
+       bus->sprom.fem.ghz5.tr_iso = (sprom[SPOFF(SSB_SPROM8_FEM5G)] &
+               SSB_SROM8_FEM_TR_ISO) >> SSB_SROM8_FEM_TR_ISO_SHIFT;
+       bus->sprom.fem.ghz5.antswlut = (sprom[SPOFF(SSB_SPROM8_FEM5G)] &
+               SSB_SROM8_FEM_ANTSWLUT) >> SSB_SROM8_FEM_ANTSWLUT_SHIFT;
 }
 
 int bcma_sprom_get(struct bcma_bus *bus)
index 4596c33a7a69c462c297d98219e13e3af3c48f37..c1d699fd5717ad892e365ee4065e9eaa74d35183 100644 (file)
@@ -152,6 +152,7 @@ struct ath_common {
        struct ath_cycle_counters cc_survey;
 
        struct ath_regulatory regulatory;
+       struct ath_regulatory reg_world_copy;
        const struct ath_ops *ops;
        const struct ath_bus_ops *bus_ops;
 
@@ -214,6 +215,10 @@ do {                                                               \
  * @ATH_DBG_HWTIMER: hardware timer handling
  * @ATH_DBG_BTCOEX: bluetooth coexistance
  * @ATH_DBG_BSTUCK: stuck beacons
+ * @ATH_DBG_MCI: Message Coexistence Interface, a private protocol
+ *     used exclusively for WLAN-BT coexistence starting from
+ *     AR9462.
+ * @ATH_DBG_DFS: radar datection
  * @ATH_DBG_ANY: enable all debugging
  *
  * The debug level is used to control the amount and type of debugging output
@@ -240,6 +245,7 @@ enum ATH_DEBUG {
        ATH_DBG_WMI             = 0x00004000,
        ATH_DBG_BSTUCK          = 0x00008000,
        ATH_DBG_MCI             = 0x00010000,
+       ATH_DBG_DFS             = 0x00020000,
        ATH_DBG_ANY             = 0xffffffff
 };
 
index 7b4c074e12fafde174793dbf50f1f6b9574ee2e8..1b4786ae00ac14f0beb096aa210e098be98cb4ea 100644 (file)
@@ -2,6 +2,9 @@ config ATH9K_HW
        tristate
 config ATH9K_COMMON
        tristate
+config ATH9K_DFS_DEBUGFS
+       def_bool y
+       depends on ATH9K_DEBUGFS && ATH9K_DFS_CERTIFIED
 
 config ATH9K
        tristate "Atheros 802.11n wireless cards support"
@@ -51,6 +54,25 @@ config ATH9K_DEBUGFS
 
          Also required for changing debug message flags at run time.
 
+config ATH9K_DFS_CERTIFIED
+       bool "Atheros DFS support for certified platforms"
+       depends on ATH9K && EXPERT
+       default n
+       ---help---
+         This option enables DFS support for initiating radiation on
+         ath9k. There is no way to dynamically detect if a card was DFS
+         certified and as such this is left as a build time option. This
+         option should only be enabled by system integrators that can
+         guarantee that all the platforms that their kernel will run on
+         have obtained appropriate regulatory body certification for a
+         respective Atheros card by using ath9k on the target shipping
+         platforms.
+
+         This is currently only a placeholder for future DFS support,
+         as DFS support requires more components that still need to be
+         developed. At this point enabling this option won't do anything
+         except increase code size.
+
 config ATH9K_RATE_CONTROL
        bool "Atheros ath9k rate control"
        depends on ATH9K
index 390797db527390ceb48731f96d1d937090da8647..da02242499af15d9049b3a2ce7913cb87ade80bc 100644 (file)
@@ -10,6 +10,8 @@ ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o
 ath9k-$(CONFIG_ATH9K_PCI) += pci.o
 ath9k-$(CONFIG_ATH9K_AHB) += ahb.o
 ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o
+ath9k-$(CONFIG_ATH9K_DFS_DEBUGFS) += dfs_debug.o
+ath9k-$(CONFIG_ATH9K_DFS_CERTIFIED) += dfs.o
 
 obj-$(CONFIG_ATH9K) += ath9k.o
 
index 95587e36ab9cfab4870b9b57ef952f822748c7f7..631fe4f2e495e8d2cb05fa665bccadf89ba110e5 100644 (file)
@@ -187,40 +187,12 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
                        isr = REG_READ(ah, AR_ISR);
        }
 
-       if (async_cause & AR_INTR_ASYNC_MASK_MCI) {
-               u32 raw_intr, rx_msg_intr;
-
-               rx_msg_intr = REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW);
-               raw_intr = REG_READ(ah, AR_MCI_INTERRUPT_RAW);
-
-               if ((raw_intr == 0xdeadbeef) || (rx_msg_intr == 0xdeadbeef))
-                       ath_dbg(common, ATH_DBG_MCI,
-                               "MCI gets 0xdeadbeef during MCI int processing"
-                               "new raw_intr=0x%08x, new rx_msg_raw=0x%08x, "
-                               "raw_intr=0x%08x, rx_msg_raw=0x%08x\n",
-                               raw_intr, rx_msg_intr, mci->raw_intr,
-                               mci->rx_msg_intr);
-               else {
-                       mci->rx_msg_intr |= rx_msg_intr;
-                       mci->raw_intr |= raw_intr;
-                       *masked |= ATH9K_INT_MCI;
-
-                       if (rx_msg_intr & AR_MCI_INTERRUPT_RX_MSG_CONT_INFO)
-                               mci->cont_status =
-                                       REG_READ(ah, AR_MCI_CONT_STATUS);
-
-                       REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, rx_msg_intr);
-                       REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, raw_intr);
-                       ath_dbg(common, ATH_DBG_MCI, "AR_INTR_SYNC_MCI\n");
-
-               }
-       }
 
        sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) & AR_INTR_SYNC_DEFAULT;
 
        *masked = 0;
 
-       if (!isr && !sync_cause)
+       if (!isr && !sync_cause && !async_cause)
                return false;
 
        if (isr) {
@@ -326,6 +298,35 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
                        ar9003_hw_bb_watchdog_read(ah);
        }
 
+       if (async_cause & AR_INTR_ASYNC_MASK_MCI) {
+               u32 raw_intr, rx_msg_intr;
+
+               rx_msg_intr = REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW);
+               raw_intr = REG_READ(ah, AR_MCI_INTERRUPT_RAW);
+
+               if ((raw_intr == 0xdeadbeef) || (rx_msg_intr == 0xdeadbeef))
+                       ath_dbg(common, ATH_DBG_MCI,
+                               "MCI gets 0xdeadbeef during MCI int processing"
+                               "new raw_intr=0x%08x, new rx_msg_raw=0x%08x, "
+                               "raw_intr=0x%08x, rx_msg_raw=0x%08x\n",
+                               raw_intr, rx_msg_intr, mci->raw_intr,
+                               mci->rx_msg_intr);
+               else {
+                       mci->rx_msg_intr |= rx_msg_intr;
+                       mci->raw_intr |= raw_intr;
+                       *masked |= ATH9K_INT_MCI;
+
+                       if (rx_msg_intr & AR_MCI_INTERRUPT_RX_MSG_CONT_INFO)
+                               mci->cont_status =
+                                       REG_READ(ah, AR_MCI_CONT_STATUS);
+
+                       REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, rx_msg_intr);
+                       REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, raw_intr);
+                       ath_dbg(common, ATH_DBG_MCI, "AR_INTR_SYNC_MCI\n");
+
+               }
+       }
+
        if (sync_cause) {
                if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) {
                        REG_WRITE(ah, AR_RC, AR_RC_HOSTIF);
index afc156a0a2e3528200cb4b4eebef19c99c09c20b..130e5dba95557621e89ef15135ccf3d496c59c1c 100644 (file)
@@ -159,6 +159,9 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd,
 /* return block-ack bitmap index given sequence and starting sequence */
 #define ATH_BA_INDEX(_st, _seq) (((_seq) - (_st)) & (IEEE80211_SEQ_MAX - 1))
 
+/* return the seqno for _start + _offset */
+#define ATH_BA_INDEX2SEQ(_seq, _offset) (((_seq) + (_offset)) & (IEEE80211_SEQ_MAX - 1))
+
 /* returns delimiter padding required given the packet length */
 #define ATH_AGGR_GET_NDELIM(_len)                                      \
        (((_len) >= ATH_AGGR_MINPLEN) ? 0 :                             \
@@ -238,6 +241,7 @@ struct ath_atx_tid {
        struct ath_node *an;
        struct ath_atx_ac *ac;
        unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)];
+       int bar_index;
        u16 seq_start;
        u16 seq_next;
        u16 baw_size;
@@ -252,9 +256,9 @@ struct ath_atx_tid {
 struct ath_node {
 #ifdef CONFIG_ATH9K_DEBUGFS
        struct list_head list; /* for sc->nodes */
+#endif
        struct ieee80211_sta *sta; /* station struct we're part of */
        struct ieee80211_vif *vif; /* interface with which we're associated */
-#endif
        struct ath_atx_tid tid[WME_NUM_TID];
        struct ath_atx_ac ac[WME_NUM_AC];
        int ps_key;
@@ -276,7 +280,6 @@ struct ath_tx_control {
 };
 
 #define ATH_TX_ERROR        0x01
-#define ATH_TX_BAR          0x02
 
 /**
  * @txq_map:  Index is mac80211 queue number.  This is
@@ -542,7 +545,7 @@ struct ath_ant_comb {
 #define DEFAULT_CACHELINE       32
 #define ATH_REGCLASSIDS_MAX     10
 #define ATH_CABQ_READY_TIME     80      /* % of beacon interval */
-#define ATH_MAX_SW_RETRIES      10
+#define ATH_MAX_SW_RETRIES      30
 #define ATH_CHAN_MAX            255
 
 #define ATH_TXPOWER_MAX         100     /* .5 dBm units */
index 6fb719d85b3748c2cc0704e5214e767e0076e859..68d972bf232d20fbc431c291853288c4b20e7fd1 100644 (file)
@@ -856,7 +856,7 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
        sc->debug.stats.txstats[qnum].tx_bytes_all += bf->bf_mpdu->len;
 
        if (bf_isampdu(bf)) {
-               if (flags & ATH_TX_BAR)
+               if (flags & ATH_TX_ERROR)
                        TX_STAT_INC(qnum, a_xretries);
                else
                        TX_STAT_INC(qnum, a_completed);
@@ -1630,6 +1630,9 @@ int ath9k_init_debug(struct ath_hw *ah)
        debugfs_create_file("debug", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
                            sc, &fops_debug);
 #endif
+
+       ath9k_dfs_init_debug(sc);
+
        debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc,
                            &fops_dma);
        debugfs_create_file("interrupt", S_IRUSR, sc->debug.debugfs_phy, sc,
index 356352ac2d6eeba7ea4834f90f44e5aa4d7aaf56..776a24ada600fc377940851a4abbe7e3fa8a2001 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "hw.h"
 #include "rc.h"
+#include "dfs_debug.h"
 
 struct ath_txq;
 struct ath_buf;
@@ -187,6 +188,7 @@ struct ath_stats {
        struct ath_interrupt_stats istats;
        struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES];
        struct ath_rx_stats rxstats;
+       struct ath_dfs_stats dfs_stats;
        u32 reset[__RESET_TYPE_MAX];
 };
 
diff --git a/drivers/net/wireless/ath/ath9k/dfs.c b/drivers/net/wireless/ath/ath9k/dfs.c
new file mode 100644 (file)
index 0000000..e4e84a9
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ * Copyright (c) 2011 Neratec Solutions AG
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "hw.h"
+#include "hw-ops.h"
+#include "ath9k.h"
+#include "dfs.h"
+#include "dfs_debug.h"
+
+/*
+ * TODO: move into or synchronize this with generic header
+ *      as soon as IF is defined
+ */
+struct dfs_radar_pulse {
+       u16 freq;
+       u64 ts;
+       u32 width;
+       u8 rssi;
+};
+
+/* internal struct to pass radar data */
+struct ath_radar_data {
+       u8 pulse_bw_info;
+       u8 rssi;
+       u8 ext_rssi;
+       u8 pulse_length_ext;
+       u8 pulse_length_pri;
+};
+
+/* convert pulse duration to usecs, considering clock mode */
+static u32 dur_to_usecs(struct ath_hw *ah, u32 dur)
+{
+       const u32 AR93X_NSECS_PER_DUR = 800;
+       const u32 AR93X_NSECS_PER_DUR_FAST = (8000 / 11);
+       u32 nsecs;
+
+       if (IS_CHAN_A_FAST_CLOCK(ah, ah->curchan))
+               nsecs = dur * AR93X_NSECS_PER_DUR_FAST;
+       else
+               nsecs = dur * AR93X_NSECS_PER_DUR;
+
+       return (nsecs + 500) / 1000;
+}
+
+#define PRI_CH_RADAR_FOUND 0x01
+#define EXT_CH_RADAR_FOUND 0x02
+static bool
+ath9k_postprocess_radar_event(struct ath_softc *sc,
+                             struct ath_radar_data *are,
+                             struct dfs_radar_pulse *drp)
+{
+       u8 rssi;
+       u16 dur;
+
+       ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_DFS,
+               "pulse_bw_info=0x%x, pri,ext len/rssi=(%u/%u, %u/%u)\n",
+               are->pulse_bw_info,
+               are->pulse_length_pri, are->rssi,
+               are->pulse_length_ext, are->ext_rssi);
+
+       /*
+        * Only the last 2 bits of the BW info are relevant, they indicate
+        * which channel the radar was detected in.
+        */
+       are->pulse_bw_info &= 0x03;
+
+       switch (are->pulse_bw_info) {
+       case PRI_CH_RADAR_FOUND:
+               /* radar in ctrl channel */
+               dur = are->pulse_length_pri;
+               DFS_STAT_INC(sc, pri_phy_errors);
+               /*
+                * cannot use ctrl channel RSSI
+                * if extension channel is stronger
+                */
+               rssi = (are->ext_rssi >= (are->rssi + 3)) ? 0 : are->rssi;
+               break;
+       case EXT_CH_RADAR_FOUND:
+               /* radar in extension channel */
+               dur = are->pulse_length_ext;
+               DFS_STAT_INC(sc, ext_phy_errors);
+               /*
+                * cannot use extension channel RSSI
+                * if control channel is stronger
+                */
+               rssi = (are->rssi >= (are->ext_rssi + 12)) ? 0 : are->ext_rssi;
+               break;
+       case (PRI_CH_RADAR_FOUND | EXT_CH_RADAR_FOUND):
+               /*
+                * Conducted testing, when pulse is on DC, both pri and ext
+                * durations are reported to be same
+                *
+                * Radiated testing, when pulse is on DC, different pri and
+                * ext durations are reported, so take the larger of the two
+                */
+               if (are->pulse_length_ext >= are->pulse_length_pri)
+                       dur = are->pulse_length_ext;
+               else
+                       dur = are->pulse_length_pri;
+               DFS_STAT_INC(sc, dc_phy_errors);
+
+               /* when both are present use stronger one */
+               rssi = (are->rssi < are->ext_rssi) ? are->ext_rssi : are->rssi;
+               break;
+       default:
+               /*
+                * Bogus bandwidth info was received in descriptor,
+                * so ignore this PHY error
+                */
+               DFS_STAT_INC(sc, bwinfo_discards);
+               return false;
+       }
+
+       if (rssi == 0) {
+               DFS_STAT_INC(sc, rssi_discards);
+               return false;
+       }
+
+       /*
+        * TODO: check chirping pulses
+        *       checks for chirping are dependent on the DFS regulatory domain
+        *       used, which is yet TBD
+        */
+
+       /* convert duration to usecs */
+       drp->width = dur_to_usecs(sc->sc_ah, dur);
+       drp->rssi = rssi;
+
+       DFS_STAT_INC(sc, pulses_detected);
+       return true;
+}
+#undef PRI_CH_RADAR_FOUND
+#undef EXT_CH_RADAR_FOUND
+
+/*
+ * DFS: check PHY-error for radar pulse and feed the detector
+ */
+void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data,
+                             struct ath_rx_status *rs, u64 mactime)
+{
+       struct ath_radar_data ard;
+       u16 datalen;
+       char *vdata_end;
+       struct dfs_radar_pulse drp;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       if ((!(rs->rs_phyerr != ATH9K_PHYERR_RADAR)) &&
+           (!(rs->rs_phyerr != ATH9K_PHYERR_FALSE_RADAR_EXT))) {
+               ath_dbg(common, ATH_DBG_DFS,
+                       "Error: rs_phyer=0x%x not a radar error\n",
+                       rs->rs_phyerr);
+               return;
+       }
+
+       datalen = rs->rs_datalen;
+       if (datalen == 0) {
+               DFS_STAT_INC(sc, datalen_discards);
+               return;
+       }
+
+       ard.rssi = rs->rs_rssi_ctl0;
+       ard.ext_rssi = rs->rs_rssi_ext0;
+
+       /*
+        * hardware stores this as 8 bit signed value.
+        * we will cap it at 0 if it is a negative number
+        */
+       if (ard.rssi & 0x80)
+               ard.rssi = 0;
+       if (ard.ext_rssi & 0x80)
+               ard.ext_rssi = 0;
+
+       vdata_end = (char *)data + datalen;
+       ard.pulse_bw_info = vdata_end[-1];
+       ard.pulse_length_ext = vdata_end[-2];
+       ard.pulse_length_pri = vdata_end[-3];
+
+       ath_dbg(common, ATH_DBG_DFS,
+               "bw_info=%d, length_pri=%d, length_ext=%d, "
+               "rssi_pri=%d, rssi_ext=%d\n",
+               ard.pulse_bw_info, ard.pulse_length_pri, ard.pulse_length_ext,
+               ard.rssi, ard.ext_rssi);
+
+       drp.freq = ah->curchan->channel;
+       drp.ts = mactime;
+       if (ath9k_postprocess_radar_event(sc, &ard, &drp)) {
+               static u64 last_ts;
+               ath_dbg(common, ATH_DBG_DFS,
+                       "ath9k_dfs_process_phyerr: channel=%d, ts=%llu, "
+                       "width=%d, rssi=%d, delta_ts=%llu\n",
+                       drp.freq, drp.ts, drp.width, drp.rssi, drp.ts-last_ts);
+               last_ts = drp.ts;
+               /*
+                * TODO: forward pulse to pattern detector
+                *
+                * ieee80211_add_radar_pulse(drp.freq, drp.ts,
+                *                           drp.width, drp.rssi);
+                */
+       }
+}
diff --git a/drivers/net/wireless/ath/ath9k/dfs.h b/drivers/net/wireless/ath/ath9k/dfs.h
new file mode 100644 (file)
index 0000000..c241285
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ * Copyright (c) 2011 Neratec Solutions AG
+ *
+ * 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 ATH9K_DFS_H
+#define ATH9K_DFS_H
+
+#if defined(CONFIG_ATH9K_DFS_CERTIFIED)
+/**
+ * ath9k_dfs_process_phyerr - process radar PHY error
+ * @sc: ath_softc
+ * @data: RX payload data
+ * @rs: RX status after processing descriptor
+ * @mactime: receive time
+ *
+ * This function is called whenever the HW DFS module detects a radar
+ * pulse and reports it as a PHY error.
+ *
+ * The radar information provided as raw payload data is validated and
+ * filtered for false pulses. Events passing all tests are forwarded to
+ * the upper layer for pattern detection.
+ */
+void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data,
+                             struct ath_rx_status *rs, u64 mactime);
+#else
+static inline void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data,
+                                           struct ath_rx_status *rs, u64 mactime) { }
+#endif
+
+#endif /* ATH9K_DFS_H */
diff --git a/drivers/net/wireless/ath/ath9k/dfs_debug.c b/drivers/net/wireless/ath/ath9k/dfs_debug.c
new file mode 100644 (file)
index 0000000..106d031
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ * Copyright (c) 2011 Neratec Solutions AG
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/debugfs.h>
+#include <linux/export.h>
+
+#include "ath9k.h"
+#include "dfs_debug.h"
+
+#define ATH9K_DFS_STAT(s, p) \
+       len += snprintf(buf + len, size - len, "%28s : %10u\n", s, \
+                       sc->debug.stats.dfs_stats.p);
+
+static ssize_t read_file_dfs(struct file *file, char __user *user_buf,
+                            size_t count, loff_t *ppos)
+{
+       struct ath_softc *sc = file->private_data;
+       struct ath9k_hw_version *hw_ver = &sc->sc_ah->hw_version;
+       char *buf;
+       unsigned int len = 0, size = 8000;
+       ssize_t retval = 0;
+
+       buf = kzalloc(size, GFP_KERNEL);
+       if (buf == NULL)
+               return -ENOMEM;
+
+       len += snprintf(buf + len, size - len, "DFS support for "
+                       "macVersion = 0x%x, macRev = 0x%x: %s\n",
+                       hw_ver->macVersion, hw_ver->macRev,
+                       (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_DFS) ?
+                                       "enabled" : "disabled");
+       ATH9K_DFS_STAT("DFS pulses detected     ", pulses_detected);
+       ATH9K_DFS_STAT("Datalen discards        ", datalen_discards);
+       ATH9K_DFS_STAT("RSSI discards           ", rssi_discards);
+       ATH9K_DFS_STAT("BW info discards        ", bwinfo_discards);
+       ATH9K_DFS_STAT("Primary channel pulses  ", pri_phy_errors);
+       ATH9K_DFS_STAT("Secondary channel pulses", ext_phy_errors);
+       ATH9K_DFS_STAT("Dual channel pulses     ", dc_phy_errors);
+
+       if (len > size)
+               len = size;
+
+       retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+       kfree(buf);
+
+       return retval;
+}
+
+static int ath9k_dfs_debugfs_open(struct inode *inode, struct file *file)
+{
+       file->private_data = inode->i_private;
+
+       return 0;
+}
+
+static const struct file_operations fops_dfs_stats = {
+       .read = read_file_dfs,
+       .open = ath9k_dfs_debugfs_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
+void ath9k_dfs_init_debug(struct ath_softc *sc)
+{
+       debugfs_create_file("dfs_stats", S_IRUSR,
+                           sc->debug.debugfs_phy, sc, &fops_dfs_stats);
+}
diff --git a/drivers/net/wireless/ath/ath9k/dfs_debug.h b/drivers/net/wireless/ath/ath9k/dfs_debug.h
new file mode 100644 (file)
index 0000000..6e1e2a7
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ * Copyright (c) 2011 Neratec Solutions AG
+ *
+ * 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 DFS_DEBUG_H
+#define DFS_DEBUG_H
+
+#include "hw.h"
+
+/**
+ * struct ath_dfs_stats - DFS Statistics
+ *
+ * @pulses_detected:  No. of pulses detected so far
+ * @datalen_discards: No. of pulses discarded due to invalid datalen
+ * @rssi_discards:    No. of pulses discarded due to invalid RSSI
+ * @bwinfo_discards:  No. of pulses discarded due to invalid BW info
+ * @pri_phy_errors:   No. of pulses reported for primary channel
+ * @ext_phy_errors:   No. of pulses reported for extension channel
+ * @dc_phy_errors:    No. of pulses reported for primary + extension channel
+ */
+struct ath_dfs_stats {
+       u32 pulses_detected;
+       u32 datalen_discards;
+       u32 rssi_discards;
+       u32 bwinfo_discards;
+       u32 pri_phy_errors;
+       u32 ext_phy_errors;
+       u32 dc_phy_errors;
+};
+
+#if defined(CONFIG_ATH9K_DFS_DEBUGFS)
+
+#define DFS_STAT_INC(sc, c) (sc->debug.stats.dfs_stats.c++)
+void ath9k_dfs_init_debug(struct ath_softc *sc);
+
+#else
+
+#define DFS_STAT_INC(sc, c) do { } while (0)
+static inline void ath9k_dfs_init_debug(struct ath_softc *sc) { }
+
+#endif /* CONFIG_ATH9K_DFS_DEBUGFS */
+
+#endif /* DFS_DEBUG_H */
index e74c233757a2d85da633f81b958dfd3a65e6dc8e..c4ad0b06bdbc9109bb2ef644c2c4dba3eb64a2c1 100644 (file)
@@ -212,4 +212,13 @@ static inline int ath9k_hw_fast_chan_change(struct ath_hw *ah,
        return ath9k_hw_private_ops(ah)->fast_chan_change(ah, chan,
                                                          ini_reloaded);
 }
+
+static inline void ath9k_hw_set_radar_params(struct ath_hw *ah)
+{
+       if (!ath9k_hw_private_ops(ah)->set_radar_params)
+               return;
+
+       ath9k_hw_private_ops(ah)->set_radar_params(ah, &ah->radar_conf);
+}
+
 #endif /* ATH9K_HW_OPS_H */
index 7f8fc65f2cb46e0fb57464d9f8de8e809fcf75b0..8cda9a1513a7838a09e1e9af6e1c13b6497999c9 100644 (file)
@@ -2277,6 +2277,30 @@ static u8 fixup_chainmask(u8 chip_chainmask, u8 eeprom_chainmask)
                return chip_chainmask;
 }
 
+/**
+ * ath9k_hw_dfs_tested - checks if DFS has been tested with used chipset
+ * @ah: the atheros hardware data structure
+ *
+ * We enable DFS support upstream on chipsets which have passed a series
+ * of tests. The testing requirements are going to be documented. Desired
+ * test requirements are documented at:
+ *
+ * http://wireless.kernel.org/en/users/Drivers/ath9k/dfs
+ *
+ * Once a new chipset gets properly tested an individual commit can be used
+ * to document the testing for DFS for that chipset.
+ */
+static bool ath9k_hw_dfs_tested(struct ath_hw *ah)
+{
+
+       switch (ah->hw_version.macVersion) {
+       /* AR9580 will likely be our first target to get testing on */
+       case AR_SREV_VERSION_9580:
+       default:
+               return false;
+       }
+}
+
 int ath9k_hw_fill_cap_info(struct ath_hw *ah)
 {
        struct ath9k_hw_capabilities *pCap = &ah->caps;
@@ -2375,12 +2399,10 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
        else
                pCap->num_gpio_pins = AR_NUM_GPIO;
 
-       if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah)) {
-               pCap->hw_caps |= ATH9K_HW_CAP_CST;
+       if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah))
                pCap->rts_aggr_limit = ATH_AMPDU_LIMIT_MAX;
-       } else {
+       else
                pCap->rts_aggr_limit = (8 * 1024);
-       }
 
 #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
        ah->rfsilent = ah->eep_ops->get_eeprom(ah, EEP_RF_SILENT);
@@ -2490,6 +2512,9 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
                pCap->pcie_lcr_offset = 0x80;
        }
 
+       if (ath9k_hw_dfs_tested(ah))
+               pCap->hw_caps |= ATH9K_HW_CAP_DFS;
+
        tx_chainmask = pCap->tx_chainmask;
        rx_chainmask = pCap->rx_chainmask;
        while (tx_chainmask || rx_chainmask) {
index 36968c0461195fededd37a5067e270de189d9ac3..615cc839f0de5b4077bcb1711536067c01af5a0d 100644 (file)
@@ -196,21 +196,21 @@ enum ath_ini_subsys {
 enum ath9k_hw_caps {
        ATH9K_HW_CAP_HT                         = BIT(0),
        ATH9K_HW_CAP_RFSILENT                   = BIT(1),
-       ATH9K_HW_CAP_CST                        = BIT(2),
-       ATH9K_HW_CAP_AUTOSLEEP                  = BIT(4),
-       ATH9K_HW_CAP_4KB_SPLITTRANS             = BIT(5),
-       ATH9K_HW_CAP_EDMA                       = BIT(6),
-       ATH9K_HW_CAP_RAC_SUPPORTED              = BIT(7),
-       ATH9K_HW_CAP_LDPC                       = BIT(8),
-       ATH9K_HW_CAP_FASTCLOCK                  = BIT(9),
-       ATH9K_HW_CAP_SGI_20                     = BIT(10),
-       ATH9K_HW_CAP_PAPRD                      = BIT(11),
-       ATH9K_HW_CAP_ANT_DIV_COMB               = BIT(12),
-       ATH9K_HW_CAP_2GHZ                       = BIT(13),
-       ATH9K_HW_CAP_5GHZ                       = BIT(14),
-       ATH9K_HW_CAP_APM                        = BIT(15),
-       ATH9K_HW_CAP_RTT                        = BIT(16),
-       ATH9K_HW_CAP_MCI                        = BIT(17),
+       ATH9K_HW_CAP_AUTOSLEEP                  = BIT(2),
+       ATH9K_HW_CAP_4KB_SPLITTRANS             = BIT(3),
+       ATH9K_HW_CAP_EDMA                       = BIT(4),
+       ATH9K_HW_CAP_RAC_SUPPORTED              = BIT(5),
+       ATH9K_HW_CAP_LDPC                       = BIT(6),
+       ATH9K_HW_CAP_FASTCLOCK                  = BIT(7),
+       ATH9K_HW_CAP_SGI_20                     = BIT(8),
+       ATH9K_HW_CAP_PAPRD                      = BIT(9),
+       ATH9K_HW_CAP_ANT_DIV_COMB               = BIT(10),
+       ATH9K_HW_CAP_2GHZ                       = BIT(11),
+       ATH9K_HW_CAP_5GHZ                       = BIT(12),
+       ATH9K_HW_CAP_APM                        = BIT(13),
+       ATH9K_HW_CAP_RTT                        = BIT(14),
+       ATH9K_HW_CAP_MCI                        = BIT(15),
+       ATH9K_HW_CAP_DFS                        = BIT(16),
 };
 
 struct ath9k_hw_capabilities {
index 41b72faca77fbca3d6ccd375c3e4a0bcc7678c22..c5df98139c4df7592d00d41958825d33b64220a0 100644 (file)
@@ -297,9 +297,22 @@ static int ath9k_reg_notifier(struct wiphy *wiphy,
 {
        struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
        struct ath_softc *sc = hw->priv;
-       struct ath_regulatory *reg = ath9k_hw_regulatory(sc->sc_ah);
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
+       int ret;
+
+       ret = ath_reg_notifier_apply(wiphy, request, reg);
+
+       /* Set tx power */
+       if (ah->curchan) {
+               sc->config.txpowlimit = 2 * ah->curchan->chan->max_power;
+               ath9k_ps_wakeup(sc);
+               ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false);
+               sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit;
+               ath9k_ps_restore(sc);
+       }
 
-       return ath_reg_notifier_apply(wiphy, request, reg);
+       return ret;
 }
 
 /*
index 7d920044d031b3370fc91ba44fc825c7796df932..7fbc4bdd4efeb6c5a8e7ea392f227fef777d0d8f 100644 (file)
@@ -644,9 +644,9 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta,
        spin_lock(&sc->nodes_lock);
        list_add(&an->list, &sc->nodes);
        spin_unlock(&sc->nodes_lock);
+#endif
        an->sta = sta;
        an->vif = vif;
-#endif
        if (sc->sc_flags & SC_OP_TXAGGR) {
                ath_tx_node_init(sc, an);
                an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
@@ -1873,7 +1873,8 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
        if (ath9k_modparam_nohwcrypt)
                return -ENOSPC;
 
-       if (vif->type == NL80211_IFTYPE_ADHOC &&
+       if ((vif->type == NL80211_IFTYPE_ADHOC ||
+            vif->type == NL80211_IFTYPE_MESH_POINT) &&
            (key->cipher == WLAN_CIPHER_SUITE_TKIP ||
             key->cipher == WLAN_CIPHER_SUITE_CCMP) &&
            !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
index d6780405d6f58eca29767056346ae7f539373f44..691bf47906e2d004ccd7e05b4ffa1129d0501015 100644 (file)
@@ -234,8 +234,8 @@ static void ath_mci_cal_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload)
        }
 }
 
-void ath_mci_process_profile(struct ath_softc *sc,
-                            struct ath_mci_profile_info *info)
+static void ath_mci_process_profile(struct ath_softc *sc,
+                                   struct ath_mci_profile_info *info)
 {
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
        struct ath_btcoex *btcoex = &sc->btcoex;
@@ -261,8 +261,8 @@ void ath_mci_process_profile(struct ath_softc *sc,
        ath_mci_update_scheme(sc);
 }
 
-void ath_mci_process_status(struct ath_softc *sc,
-                           struct ath_mci_profile_status *status)
+static void ath_mci_process_status(struct ath_softc *sc,
+                                  struct ath_mci_profile_status *status)
 {
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
        struct ath_btcoex *btcoex = &sc->btcoex;
index b71bdeda7c78a1d7742df643aa3d9307d6d8297a..29e3e51d078f52e661f0693f267d6e2f031f4479 100644 (file)
@@ -128,10 +128,6 @@ struct ath_mci_coex {
 };
 
 void ath_mci_flush_profile(struct ath_mci_profile *mci);
-void ath_mci_process_profile(struct ath_softc *sc,
-                            struct ath_mci_profile_info *info);
-void ath_mci_process_status(struct ath_softc *sc,
-                           struct ath_mci_profile_status *status);
 int ath_mci_setup(struct ath_softc *sc);
 void ath_mci_cleanup(struct ath_softc *sc);
 void ath_mci_intr(struct ath_softc *sc);
index 888abc2be3a547d6f85ad32723fd2d2910c5582e..528d5f3e868c712a7b2372dc8616e1581205bddc 100644 (file)
@@ -1271,7 +1271,9 @@ static void ath_rc_init(struct ath_softc *sc,
 
        ath_rc_priv->max_valid_rate = k;
        ath_rc_sort_validrates(rate_table, ath_rc_priv);
-       ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4];
+       ath_rc_priv->rate_max_phy = (k > 4) ?
+                                       ath_rc_priv->valid_rate_index[k-4] :
+                                       ath_rc_priv->valid_rate_index[k-1];
        ath_rc_priv->rate_table = rate_table;
 
        ath_dbg(common, ATH_DBG_CONFIG,
index e0318415c2a0099575c03c77d712cc99e07f6774..ad5176de07dc93dc65dc83f52487e8c448de36f3 100644 (file)
@@ -1823,6 +1823,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
                hdr = (struct ieee80211_hdr *) (hdr_skb->data + rx_status_len);
                rxs = IEEE80211_SKB_RXCB(hdr_skb);
                if (ieee80211_is_beacon(hdr->frame_control) &&
+                   !is_zero_ether_addr(common->curbssid) &&
                    !compare_ether_addr(hdr->addr3, common->curbssid))
                        rs.is_mybeacon = true;
                else
index 9e65c3198ca7b9272f323fc21cb1d50fa203ac74..23e80e63bca9f2b10b2432a38a87d727e990606c 100644 (file)
@@ -53,7 +53,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
                            int tx_flags, struct ath_txq *txq);
 static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
                                struct ath_txq *txq, struct list_head *bf_q,
-                               struct ath_tx_status *ts, int txok, int sendbar);
+                               struct ath_tx_status *ts, int txok);
 static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
                             struct list_head *head, bool internal);
 static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
@@ -150,6 +150,12 @@ static struct ath_frame_info *get_frame_info(struct sk_buff *skb)
        return (struct ath_frame_info *) &tx_info->rate_driver_data[0];
 }
 
+static void ath_send_bar(struct ath_atx_tid *tid, u16 seqno)
+{
+       ieee80211_send_bar(tid->an->vif, tid->an->sta->addr, tid->tidno,
+                          seqno << IEEE80211_SEQ_SEQ_SHIFT);
+}
+
 static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
 {
        struct ath_txq *txq = tid->ac->txq;
@@ -158,25 +164,24 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
        struct list_head bf_head;
        struct ath_tx_status ts;
        struct ath_frame_info *fi;
+       bool sendbar = false;
 
        INIT_LIST_HEAD(&bf_head);
 
        memset(&ts, 0, sizeof(ts));
-       spin_lock_bh(&txq->axq_lock);
 
        while ((skb = __skb_dequeue(&tid->buf_q))) {
                fi = get_frame_info(skb);
                bf = fi->bf;
 
-               spin_unlock_bh(&txq->axq_lock);
                if (bf && fi->retries) {
                        list_add_tail(&bf->list, &bf_head);
                        ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
-                       ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1);
+                       ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
+                       sendbar = true;
                } else {
                        ath_tx_send_normal(sc, txq, NULL, skb);
                }
-               spin_lock_bh(&txq->axq_lock);
        }
 
        if (tid->baw_head == tid->baw_tail) {
@@ -184,7 +189,8 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
                tid->state &= ~AGGR_CLEANUP;
        }
 
-       spin_unlock_bh(&txq->axq_lock);
+       if (sendbar)
+               ath_send_bar(tid, tid->seq_start);
 }
 
 static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
@@ -200,6 +206,8 @@ static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
        while (tid->baw_head != tid->baw_tail && !test_bit(tid->baw_head, tid->tx_buf)) {
                INCR(tid->seq_start, IEEE80211_SEQ_MAX);
                INCR(tid->baw_head, ATH_TID_MAX_BUFS);
+               if (tid->bar_index >= 0)
+                       tid->bar_index--;
        }
 }
 
@@ -243,9 +251,7 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq,
                bf = fi->bf;
 
                if (!bf) {
-                       spin_unlock(&txq->axq_lock);
                        ath_tx_complete(sc, skb, ATH_TX_ERROR, txq);
-                       spin_lock(&txq->axq_lock);
                        continue;
                }
 
@@ -254,24 +260,26 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq,
                if (fi->retries)
                        ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
 
-               spin_unlock(&txq->axq_lock);
-               ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
-               spin_lock(&txq->axq_lock);
+               ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
        }
 
        tid->seq_next = tid->seq_start;
        tid->baw_tail = tid->baw_head;
+       tid->bar_index = -1;
 }
 
 static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq,
-                            struct sk_buff *skb)
+                            struct sk_buff *skb, int count)
 {
        struct ath_frame_info *fi = get_frame_info(skb);
        struct ath_buf *bf = fi->bf;
        struct ieee80211_hdr *hdr;
+       int prev = fi->retries;
 
        TX_STAT_INC(txq->axq_qnum, a_retries);
-       if (fi->retries++ > 0)
+       fi->retries += count;
+
+       if (prev > 0)
                return;
 
        hdr = (struct ieee80211_hdr *)skb->data;
@@ -370,7 +378,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
        struct ath_buf *bf_next, *bf_last = bf->bf_lastbf;
        struct list_head bf_head;
        struct sk_buff_head bf_pending;
-       u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0;
+       u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0, seq_first;
        u32 ba[WME_BA_BMP_SIZE >> 5];
        int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
        bool rc_update = true;
@@ -379,6 +387,8 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
        int nframes;
        u8 tidno;
        bool flush = !!(ts->ts_status & ATH9K_TX_FLUSH);
+       int i, retries;
+       int bar_index = -1;
 
        skb = bf->bf_mpdu;
        hdr = (struct ieee80211_hdr *)skb->data;
@@ -387,6 +397,10 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
 
        memcpy(rates, tx_info->control.rates, sizeof(rates));
 
+       retries = ts->ts_longretry + 1;
+       for (i = 0; i < ts->ts_rateindex; i++)
+               retries += rates[i].count;
+
        rcu_read_lock();
 
        sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2);
@@ -400,8 +414,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
                        if (!bf->bf_stale || bf_next != NULL)
                                list_move_tail(&bf->list, &bf_head);
 
-                       ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
-                               0, 0);
+                       ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, 0);
 
                        bf = bf_next;
                }
@@ -411,6 +424,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
        an = (struct ath_node *)sta->drv_priv;
        tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
        tid = ATH_AN_2_TID(an, tidno);
+       seq_first = tid->seq_start;
 
        /*
         * The hardware occasionally sends a tx status for the wrong TID.
@@ -460,25 +474,25 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
                } else if (!isaggr && txok) {
                        /* transmit completion */
                        acked_cnt++;
+               } else if ((tid->state & AGGR_CLEANUP) || !retry) {
+                       /*
+                        * cleanup in progress, just fail
+                        * the un-acked sub-frames
+                        */
+                       txfail = 1;
+               } else if (flush) {
+                       txpending = 1;
+               } else if (fi->retries < ATH_MAX_SW_RETRIES) {
+                       if (txok || !an->sleeping)
+                               ath_tx_set_retry(sc, txq, bf->bf_mpdu,
+                                                retries);
+
+                       txpending = 1;
                } else {
-                       if ((tid->state & AGGR_CLEANUP) || !retry) {
-                               /*
-                                * cleanup in progress, just fail
-                                * the un-acked sub-frames
-                                */
-                               txfail = 1;
-                       } else if (flush) {
-                               txpending = 1;
-                       } else if (fi->retries < ATH_MAX_SW_RETRIES) {
-                               if (txok || !an->sleeping)
-                                       ath_tx_set_retry(sc, txq, bf->bf_mpdu);
-
-                               txpending = 1;
-                       } else {
-                               txfail = 1;
-                               sendbar = 1;
-                               txfail_cnt++;
-                       }
+                       txfail = 1;
+                       txfail_cnt++;
+                       bar_index = max_t(int, bar_index,
+                               ATH_BA_INDEX(seq_first, seqno));
                }
 
                /*
@@ -495,9 +509,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
                         * complete the acked-ones/xretried ones; update
                         * block-ack window
                         */
-                       spin_lock_bh(&txq->axq_lock);
                        ath_tx_update_baw(sc, tid, seqno);
-                       spin_unlock_bh(&txq->axq_lock);
 
                        if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
                                memcpy(tx_info->control.rates, rates, sizeof(rates));
@@ -506,33 +518,30 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
                        }
 
                        ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
-                               !txfail, sendbar);
+                               !txfail);
                } else {
                        /* retry the un-acked ones */
-                       if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) {
-                               if (bf->bf_next == NULL && bf_last->bf_stale) {
-                                       struct ath_buf *tbf;
-
-                                       tbf = ath_clone_txbuf(sc, bf_last);
-                                       /*
-                                        * Update tx baw and complete the
-                                        * frame with failed status if we
-                                        * run out of tx buf.
-                                        */
-                                       if (!tbf) {
-                                               spin_lock_bh(&txq->axq_lock);
-                                               ath_tx_update_baw(sc, tid, seqno);
-                                               spin_unlock_bh(&txq->axq_lock);
-
-                                               ath_tx_complete_buf(sc, bf, txq,
-                                                                   &bf_head,
-                                                                   ts, 0,
-                                                                   !flush);
-                                               break;
-                                       }
-
-                                       fi->bf = tbf;
+                       if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
+                           bf->bf_next == NULL && bf_last->bf_stale) {
+                               struct ath_buf *tbf;
+
+                               tbf = ath_clone_txbuf(sc, bf_last);
+                               /*
+                                * Update tx baw and complete the
+                                * frame with failed status if we
+                                * run out of tx buf.
+                                */
+                               if (!tbf) {
+                                       ath_tx_update_baw(sc, tid, seqno);
+
+                                       ath_tx_complete_buf(sc, bf, txq,
+                                                           &bf_head, ts, 0);
+                                       bar_index = max_t(int, bar_index,
+                                               ATH_BA_INDEX(seq_first, seqno));
+                                       break;
                                }
+
+                               fi->bf = tbf;
                        }
 
                        /*
@@ -545,12 +554,18 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
                bf = bf_next;
        }
 
+       if (bar_index >= 0) {
+               u16 bar_seq = ATH_BA_INDEX2SEQ(seq_first, bar_index);
+               ath_send_bar(tid, ATH_BA_INDEX2SEQ(seq_first, bar_index + 1));
+               if (BAW_WITHIN(tid->seq_start, tid->baw_size, bar_seq))
+                       tid->bar_index = ATH_BA_INDEX(tid->seq_start, bar_seq);
+       }
+
        /* prepend un-acked frames to the beginning of the pending frame queue */
        if (!skb_queue_empty(&bf_pending)) {
                if (an->sleeping)
                        ieee80211_sta_set_buffered(sta, tid->tidno, true);
 
-               spin_lock_bh(&txq->axq_lock);
                skb_queue_splice(&bf_pending, &tid->buf_q);
                if (!an->sleeping) {
                        ath_tx_queue_tid(txq, tid);
@@ -558,7 +573,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
                        if (ts->ts_status & ATH9K_TXERR_FILT)
                                tid->ac->clear_ps_filter = true;
                }
-               spin_unlock_bh(&txq->axq_lock);
        }
 
        if (tid->state & AGGR_CLEANUP)
@@ -617,24 +631,26 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
        max_4ms_framelen = ATH_AMPDU_LIMIT_MAX;
 
        for (i = 0; i < 4; i++) {
-               if (rates[i].count) {
-                       int modeidx;
-                       if (!(rates[i].flags & IEEE80211_TX_RC_MCS)) {
-                               legacy = 1;
-                               break;
-                       }
-
-                       if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
-                               modeidx = MCS_HT40;
-                       else
-                               modeidx = MCS_HT20;
+               int modeidx;
 
-                       if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
-                               modeidx++;
+               if (!rates[i].count)
+                       continue;
 
-                       frmlen = ath_max_4ms_framelen[modeidx][rates[i].idx];
-                       max_4ms_framelen = min(max_4ms_framelen, frmlen);
+               if (!(rates[i].flags & IEEE80211_TX_RC_MCS)) {
+                       legacy = 1;
+                       break;
                }
+
+               if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+                       modeidx = MCS_HT40;
+               else
+                       modeidx = MCS_HT20;
+
+               if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
+                       modeidx++;
+
+               frmlen = ath_max_4ms_framelen[modeidx][rates[i].idx];
+               max_4ms_framelen = min(max_4ms_framelen, frmlen);
        }
 
        /*
@@ -770,8 +786,6 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
 
                bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR;
                seqno = bf->bf_state.seqno;
-               if (!bf_first)
-                       bf_first = bf;
 
                /* do not step over block-ack window */
                if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno)) {
@@ -779,6 +793,21 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
                        break;
                }
 
+               if (tid->bar_index > ATH_BA_INDEX(tid->seq_start, seqno)) {
+                       struct ath_tx_status ts = {};
+                       struct list_head bf_head;
+
+                       INIT_LIST_HEAD(&bf_head);
+                       list_add(&bf->list, &bf_head);
+                       __skb_unlink(skb, &tid->buf_q);
+                       ath_tx_update_baw(sc, tid, seqno);
+                       ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
+                       continue;
+               }
+
+               if (!bf_first)
+                       bf_first = bf;
+
                if (!rl) {
                        aggr_limit = ath_lookup_rate(sc, bf, tid);
                        rl = 1;
@@ -1121,6 +1150,7 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
        txtid->state |= AGGR_ADDBA_PROGRESS;
        txtid->paused = true;
        *ssn = txtid->seq_start = txtid->seq_next;
+       txtid->bar_index = -1;
 
        memset(txtid->tx_buf, 0, sizeof(txtid->tx_buf));
        txtid->baw_head = txtid->baw_tail = 0;
@@ -1155,9 +1185,9 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
                txtid->state |= AGGR_CLEANUP;
        else
                txtid->state &= ~AGGR_ADDBA_COMPLETE;
-       spin_unlock_bh(&txq->axq_lock);
 
        ath_tx_flush_tid(sc, txtid);
+       spin_unlock_bh(&txq->axq_lock);
 }
 
 void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
@@ -1399,8 +1429,6 @@ static bool bf_is_ampdu_not_probing(struct ath_buf *bf)
 
 static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq,
                               struct list_head *list, bool retry_tx)
-       __releases(txq->axq_lock)
-       __acquires(txq->axq_lock)
 {
        struct ath_buf *bf, *lastbf;
        struct list_head bf_head;
@@ -1427,13 +1455,11 @@ static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq,
                if (bf_is_ampdu_not_probing(bf))
                        txq->axq_ampdu_depth--;
 
-               spin_unlock_bh(&txq->axq_lock);
                if (bf_isampdu(bf))
                        ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0,
                                             retry_tx);
                else
-                       ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
-               spin_lock_bh(&txq->axq_lock);
+                       ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
        }
 }
 
@@ -1560,11 +1586,9 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
                                break;
                }
 
-               if (!list_empty(&ac->tid_q)) {
-                       if (!ac->sched) {
-                               ac->sched = true;
-                               list_add_tail(&ac->list, &txq->axq_acq);
-                       }
+               if (!list_empty(&ac->tid_q) && !ac->sched) {
+                       ac->sched = true;
+                       list_add_tail(&ac->list, &txq->axq_acq);
                }
 
                if (ac == last_ac ||
@@ -1707,10 +1731,6 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
        list_add_tail(&bf->list, &bf_head);
        bf->bf_state.bf_type = 0;
 
-       /* update starting sequence number for subsequent ADDBA request */
-       if (tid)
-               INCR(tid->seq_start, IEEE80211_SEQ_MAX);
-
        bf->bf_lastbf = bf;
        ath_tx_fill_desc(sc, bf, txq, fi->framelen);
        ath_tx_txqaddbuf(sc, txq, &bf_head, false);
@@ -1818,7 +1838,6 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
        struct ath_buf *bf;
        u8 tidno;
 
-       spin_lock_bh(&txctl->txq->axq_lock);
        if ((sc->sc_flags & SC_OP_TXAGGR) && txctl->an &&
                ieee80211_is_data_qos(hdr->frame_control)) {
                tidno = ieee80211_get_qos_ctl(hdr)[0] &
@@ -1837,7 +1856,7 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
        } else {
                bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
                if (!bf)
-                       goto out;
+                       return;
 
                bf->bf_state.bfs_paprd = txctl->paprd;
 
@@ -1846,9 +1865,6 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
 
                ath_tx_send_normal(sc, txctl->txq, tid, skb);
        }
-
-out:
-       spin_unlock_bh(&txctl->txq->axq_lock);
 }
 
 /* Upon failure caller should free skb */
@@ -1915,9 +1931,11 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
                ieee80211_stop_queue(sc->hw, q);
                txq->stopped = 1;
        }
-       spin_unlock_bh(&txq->axq_lock);
 
        ath_tx_start_dma(sc, skb, txctl);
+
+       spin_unlock_bh(&txq->axq_lock);
+
        return 0;
 }
 
@@ -1936,9 +1954,6 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
 
        ath_dbg(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb);
 
-       if (tx_flags & ATH_TX_BAR)
-               tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
-
        if (!(tx_flags & ATH_TX_ERROR))
                /* Frame was ACKed */
                tx_info->flags |= IEEE80211_TX_STAT_ACK;
@@ -1966,7 +1981,6 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
 
        q = skb_get_queue_mapping(skb);
        if (txq == sc->tx.txq_map[q]) {
-               spin_lock_bh(&txq->axq_lock);
                if (WARN_ON(--txq->pending_frames < 0))
                        txq->pending_frames = 0;
 
@@ -1974,7 +1988,6 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
                        ieee80211_wake_queue(sc->hw, q);
                        txq->stopped = 0;
                }
-               spin_unlock_bh(&txq->axq_lock);
        }
 
        ieee80211_tx_status(hw, skb);
@@ -1982,16 +1995,13 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
 
 static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
                                struct ath_txq *txq, struct list_head *bf_q,
-                               struct ath_tx_status *ts, int txok, int sendbar)
+                               struct ath_tx_status *ts, int txok)
 {
        struct sk_buff *skb = bf->bf_mpdu;
        struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
        unsigned long flags;
        int tx_flags = 0;
 
-       if (sendbar)
-               tx_flags = ATH_TX_BAR;
-
        if (!txok)
                tx_flags |= ATH_TX_ERROR;
 
@@ -2083,8 +2093,6 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
 static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
                                  struct ath_tx_status *ts, struct ath_buf *bf,
                                  struct list_head *bf_head)
-       __releases(txq->axq_lock)
-       __acquires(txq->axq_lock)
 {
        int txok;
 
@@ -2094,16 +2102,12 @@ static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
        if (bf_is_ampdu_not_probing(bf))
                txq->axq_ampdu_depth--;
 
-       spin_unlock_bh(&txq->axq_lock);
-
        if (!bf_isampdu(bf)) {
                ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok);
-               ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok, 0);
+               ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok);
        } else
                ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok, true);
 
-       spin_lock_bh(&txq->axq_lock);
-
        if (sc->sc_flags & SC_OP_TXAGGR)
                ath_txq_schedule(sc, txq);
 }
index 65ecb5bab25a2a0a0c1e64d5122397238ab1e0ca..10dea37431b320ec31016203bb8a3bb47bf40070 100644 (file)
@@ -21,6 +21,8 @@
 #include "regd.h"
 #include "regd_common.h"
 
+static int __ath_regd_init(struct ath_regulatory *reg);
+
 /*
  * This is a set of common rules used by our world regulatory domains.
  * We have 12 world regulatory domains. To save space we consolidate
@@ -347,10 +349,26 @@ static void ath_reg_apply_world_flags(struct wiphy *wiphy,
        }
 }
 
+static u16 ath_regd_find_country_by_name(char *alpha2)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
+               if (!memcmp(allCountries[i].isoName, alpha2, 2))
+                       return allCountries[i].countryCode;
+       }
+
+       return -1;
+}
+
 int ath_reg_notifier_apply(struct wiphy *wiphy,
                           struct regulatory_request *request,
                           struct ath_regulatory *reg)
 {
+       struct ath_common *common = container_of(reg, struct ath_common,
+                                                regulatory);
+       u16 country_code;
+
        /* We always apply this */
        ath_reg_apply_radar_flags(wiphy);
 
@@ -363,14 +381,37 @@ int ath_reg_notifier_apply(struct wiphy *wiphy,
                return 0;
 
        switch (request->initiator) {
-       case NL80211_REGDOM_SET_BY_DRIVER:
        case NL80211_REGDOM_SET_BY_CORE:
+               /*
+                * If common->reg_world_copy is world roaming it means we *were*
+                * world roaming... so we now have to restore that data.
+                */
+               if (!ath_is_world_regd(&common->reg_world_copy))
+                       break;
+
+               memcpy(reg, &common->reg_world_copy,
+                      sizeof(struct ath_regulatory));
+               break;
+       case NL80211_REGDOM_SET_BY_DRIVER:
        case NL80211_REGDOM_SET_BY_USER:
                break;
        case NL80211_REGDOM_SET_BY_COUNTRY_IE:
-               if (ath_is_world_regd(reg))
-                       ath_reg_apply_world_flags(wiphy, request->initiator,
-                                                 reg);
+               if (!ath_is_world_regd(reg))
+                       break;
+
+               country_code = ath_regd_find_country_by_name(request->alpha2);
+               if (country_code == (u16) -1)
+                       break;
+
+               reg->current_rd = COUNTRY_ERD_FLAG;
+               reg->current_rd |= country_code;
+
+               printk(KERN_DEBUG "ath: regdomain 0x%0x updated by CountryIE\n",
+                       reg->current_rd);
+               __ath_regd_init(reg);
+
+               ath_reg_apply_world_flags(wiphy, request->initiator, reg);
+
                break;
        }
 
@@ -508,11 +549,7 @@ static void ath_regd_sanitize(struct ath_regulatory *reg)
        reg->current_rd = 0x64;
 }
 
-int
-ath_regd_init(struct ath_regulatory *reg,
-             struct wiphy *wiphy,
-             int (*reg_notifier)(struct wiphy *wiphy,
-                                 struct regulatory_request *request))
+static int __ath_regd_init(struct ath_regulatory *reg)
 {
        struct country_code_to_enum_rd *country = NULL;
        u16 regdmn;
@@ -583,7 +620,29 @@ ath_regd_init(struct ath_regulatory *reg,
        printk(KERN_DEBUG "ath: Regpair used: 0x%0x\n",
                reg->regpair->regDmnEnum);
 
+       return 0;
+}
+
+int
+ath_regd_init(struct ath_regulatory *reg,
+             struct wiphy *wiphy,
+             int (*reg_notifier)(struct wiphy *wiphy,
+                                 struct regulatory_request *request))
+{
+       struct ath_common *common = container_of(reg, struct ath_common,
+                                                regulatory);
+       int r;
+
+       r = __ath_regd_init(reg);
+       if (r)
+               return r;
+
+       if (ath_is_world_regd(reg))
+               memcpy(&common->reg_world_copy, reg,
+                      sizeof(struct ath_regulatory));
+
        ath_regd_init_wiphy(reg, wiphy, reg_notifier);
+
        return 0;
 }
 EXPORT_SYMBOL(ath_regd_init);
index b17d9b6c33a51e5a5946c5a9f3b12bdab3541e50..c8fa2cd97e6464d53f5bf44d4684db7daf11db32 100644 (file)
@@ -228,10 +228,98 @@ static void b43_chantab_radio_2056_upload(struct b43_wldev *dev,
 static void b43_radio_2056_setup(struct b43_wldev *dev,
                                const struct b43_nphy_channeltab_entry_rev3 *e)
 {
+       struct ssb_sprom *sprom = dev->dev->bus_sprom;
+       enum ieee80211_band band = b43_current_band(dev->wl);
+       u16 offset;
+       u8 i;
+       u16 bias, cbias, pag_boost, pgag_boost, mixg_boost, padg_boost;
+
        B43_WARN_ON(dev->phy.rev < 3);
 
        b43_chantab_radio_2056_upload(dev, e);
-       /* TODO */
+       b2056_upload_syn_pll_cp2(dev, band == IEEE80211_BAND_5GHZ);
+
+       if (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR &&
+           b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+               b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 0x1F);
+               b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, 0x1F);
+               if (dev->dev->chip_id == 0x4716) {
+                       b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x14);
+                       b43_radio_write(dev, B2056_SYN_PLL_CP2, 0);
+               } else {
+                       b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x0B);
+                       b43_radio_write(dev, B2056_SYN_PLL_CP2, 0x14);
+               }
+       }
+       if (sprom->boardflags2_lo & B43_BFL2_APLL_WAR &&
+           b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
+               b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 0x1F);
+               b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, 0x1F);
+               b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x05);
+               b43_radio_write(dev, B2056_SYN_PLL_CP2, 0x0C);
+       }
+
+       if (dev->phy.n->ipa2g_on && band == IEEE80211_BAND_2GHZ) {
+               for (i = 0; i < 2; i++) {
+                       offset = i ? B2056_TX1 : B2056_TX0;
+                       if (dev->phy.rev >= 5) {
+                               b43_radio_write(dev,
+                                       offset | B2056_TX_PADG_IDAC, 0xcc);
+
+                               if (dev->dev->chip_id == 0x4716) {
+                                       bias = 0x40;
+                                       cbias = 0x45;
+                                       pag_boost = 0x5;
+                                       pgag_boost = 0x33;
+                                       mixg_boost = 0x55;
+                               } else {
+                                       bias = 0x25;
+                                       cbias = 0x20;
+                                       pag_boost = 0x4;
+                                       pgag_boost = 0x03;
+                                       mixg_boost = 0x65;
+                               }
+                               padg_boost = 0x77;
+
+                               b43_radio_write(dev,
+                                       offset | B2056_TX_INTPAG_IMAIN_STAT,
+                                       bias);
+                               b43_radio_write(dev,
+                                       offset | B2056_TX_INTPAG_IAUX_STAT,
+                                       bias);
+                               b43_radio_write(dev,
+                                       offset | B2056_TX_INTPAG_CASCBIAS,
+                                       cbias);
+                               b43_radio_write(dev,
+                                       offset | B2056_TX_INTPAG_BOOST_TUNE,
+                                       pag_boost);
+                               b43_radio_write(dev,
+                                       offset | B2056_TX_PGAG_BOOST_TUNE,
+                                       pgag_boost);
+                               b43_radio_write(dev,
+                                       offset | B2056_TX_PADG_BOOST_TUNE,
+                                       padg_boost);
+                               b43_radio_write(dev,
+                                       offset | B2056_TX_MIXG_BOOST_TUNE,
+                                       mixg_boost);
+                       } else {
+                               bias = dev->phy.is_40mhz ? 0x40 : 0x20;
+                               b43_radio_write(dev,
+                                       offset | B2056_TX_INTPAG_IMAIN_STAT,
+                                       bias);
+                               b43_radio_write(dev,
+                                       offset | B2056_TX_INTPAG_IAUX_STAT,
+                                       bias);
+                               b43_radio_write(dev,
+                                       offset | B2056_TX_INTPAG_CASCBIAS,
+                                       0x30);
+                       }
+                       b43_radio_write(dev, offset | B2056_TX_PA_SPARE1, 0xee);
+               }
+       } else if (dev->phy.n->ipa5g_on && band == IEEE80211_BAND_5GHZ) {
+               /* TODO */
+       }
+
        udelay(50);
        /* VCO calibration */
        b43_radio_write(dev, B2056_SYN_PLL_VCOCAL12, 0x00);
@@ -387,7 +475,9 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
        if (nphy->hang_avoid)
                b43_nphy_stay_in_carrier_search(dev, 1);
 
-       if (dev->phy.rev >= 3) {
+       if (dev->phy.rev >= 7) {
+               txpi[0] = txpi[1] = 30;
+       } else if (dev->phy.rev >= 3) {
                txpi[0] = 40;
                txpi[1] = 40;
        } else if (sprom->revision < 4) {
@@ -411,6 +501,9 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
                        txpi[1] = 91;
                }
        }
+       if (dev->phy.rev < 7 &&
+           (txpi[0] < 40 || txpi[0] > 100 || txpi[1] < 40 || txpi[1] > 10))
+               txpi[0] = txpi[1] = 91;
 
        /*
        for (i = 0; i < 2; i++) {
@@ -421,15 +514,31 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
 
        for (i = 0; i < 2; i++) {
                if (dev->phy.rev >= 3) {
-                       /* FIXME: support 5GHz */
-                       txgain = b43_ntab_tx_gain_rev3plus_2ghz[txpi[i]];
+                       if (b43_nphy_ipa(dev)) {
+                               txgain = *(b43_nphy_get_ipa_gain_table(dev) +
+                                               txpi[i]);
+                       } else if (b43_current_band(dev->wl) ==
+                                  IEEE80211_BAND_5GHZ) {
+                               /* FIXME: use 5GHz tables */
+                               txgain =
+                                       b43_ntab_tx_gain_rev3plus_2ghz[txpi[i]];
+                       } else {
+                               if (dev->phy.rev >= 5 &&
+                                   sprom->fem.ghz5.extpa_gain == 3)
+                                       ; /* FIXME: 5GHz_txgain_HiPwrEPA */
+                               txgain =
+                                       b43_ntab_tx_gain_rev3plus_2ghz[txpi[i]];
+                       }
                        radio_gain = (txgain >> 16) & 0x1FFFF;
                } else {
                        txgain = b43_ntab_tx_gain_rev0_1_2[txpi[i]];
                        radio_gain = (txgain >> 16) & 0x1FFF;
                }
 
-               dac_gain = (txgain >> 8) & 0x3F;
+               if (dev->phy.rev >= 7)
+                       dac_gain = (txgain >> 8) & 0x7;
+               else
+                       dac_gain = (txgain >> 8) & 0x3F;
                bbmult = txgain & 0xFF;
 
                if (dev->phy.rev >= 3) {
@@ -459,7 +568,8 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
                        u32 tmp32;
                        u16 reg = (i == 0) ?
                                B43_NPHY_PAPD_EN0 : B43_NPHY_PAPD_EN1;
-                       tmp32 = b43_ntab_read(dev, B43_NTAB32(26 + i, txpi[i]));
+                       tmp32 = b43_ntab_read(dev, B43_NTAB32(26 + i,
+                                                             576 + txpi[i]));
                        b43_phy_maskset(dev, reg, 0xE00F, (u32) tmp32 << 4);
                        b43_phy_set(dev, reg, 0x4);
                }
@@ -1493,8 +1603,8 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
        struct ssb_sprom *sprom = dev->dev->bus_sprom;
 
        /* TX to RX */
-       u8 tx2rx_events[9] = { 0x4, 0x3, 0x6, 0x5, 0x2, 0x1, 0x8, 0x1F };
-       u8 tx2rx_delays[9] = { 8, 4, 2, 2, 4, 4, 6, 1 };
+       u8 tx2rx_events[8] = { 0x4, 0x3, 0x6, 0x5, 0x2, 0x1, 0x8, 0x1F };
+       u8 tx2rx_delays[8] = { 8, 4, 2, 2, 4, 4, 6, 1 };
        /* RX to TX */
        u8 rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3,
                                        0x1F };
@@ -1505,6 +1615,9 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
        u16 tmp16;
        u32 tmp32;
 
+       b43_phy_write(dev, 0x23f, 0x1f8);
+       b43_phy_write(dev, 0x240, 0x1f8);
+
        tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0));
        tmp32 &= 0xffffff;
        b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32);
@@ -1520,12 +1633,13 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
        b43_phy_write(dev, 0x2AE, 0x000C);
 
        /* TX to RX */
-       b43_nphy_set_rf_sequence(dev, 1, tx2rx_events, tx2rx_delays, 9);
+       b43_nphy_set_rf_sequence(dev, 1, tx2rx_events, tx2rx_delays,
+                                ARRAY_SIZE(tx2rx_events));
 
        /* RX to TX */
        if (b43_nphy_ipa(dev))
-               b43_nphy_set_rf_sequence(dev, 1, rx2tx_events_ipa,
-                                        rx2tx_delays_ipa, 9);
+               b43_nphy_set_rf_sequence(dev, 0, rx2tx_events_ipa,
+                               rx2tx_delays_ipa, ARRAY_SIZE(rx2tx_events_ipa));
        if (nphy->hw_phyrxchain != 3 &&
            nphy->hw_phyrxchain != nphy->hw_phytxchain) {
                if (b43_nphy_ipa(dev)) {
@@ -1533,7 +1647,8 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
                        rx2tx_delays[6] = 1;
                        rx2tx_events[7] = 0x1F;
                }
-               b43_nphy_set_rf_sequence(dev, 1, rx2tx_events, rx2tx_delays, 9);
+               b43_nphy_set_rf_sequence(dev, 1, rx2tx_events, rx2tx_delays,
+                                        ARRAY_SIZE(rx2tx_events));
        }
 
        tmp16 = (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) ?
@@ -1547,8 +1662,8 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
 
        b43_nphy_gain_ctrl_workarounds(dev);
 
-       b43_ntab_write(dev, B43_NTAB32(8, 0), 2);
-       b43_ntab_write(dev, B43_NTAB32(8, 16), 2);
+       b43_ntab_write(dev, B43_NTAB16(8, 0), 2);
+       b43_ntab_write(dev, B43_NTAB16(8, 16), 2);
 
        /* TODO */
 
@@ -1560,6 +1675,8 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
        b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_AUX, 0x07);
        b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_LOB_BIAS, 0x88);
        b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_LOB_BIAS, 0x88);
+       b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_CMFB_IDAC, 0x00);
+       b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_CMFB_IDAC, 0x00);
        b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
        b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
 
@@ -1584,18 +1701,18 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
                                0x70);
        }
 
-       b43_phy_write(dev, 0x224, 0x039C);
-       b43_phy_write(dev, 0x225, 0x0357);
-       b43_phy_write(dev, 0x226, 0x0317);
-       b43_phy_write(dev, 0x227, 0x02D7);
-       b43_phy_write(dev, 0x228, 0x039C);
-       b43_phy_write(dev, 0x229, 0x0357);
-       b43_phy_write(dev, 0x22A, 0x0317);
-       b43_phy_write(dev, 0x22B, 0x02D7);
-       b43_phy_write(dev, 0x22C, 0x039C);
-       b43_phy_write(dev, 0x22D, 0x0357);
-       b43_phy_write(dev, 0x22E, 0x0317);
-       b43_phy_write(dev, 0x22F, 0x02D7);
+       b43_phy_write(dev, 0x224, 0x03eb);
+       b43_phy_write(dev, 0x225, 0x03eb);
+       b43_phy_write(dev, 0x226, 0x0341);
+       b43_phy_write(dev, 0x227, 0x0341);
+       b43_phy_write(dev, 0x228, 0x042b);
+       b43_phy_write(dev, 0x229, 0x042b);
+       b43_phy_write(dev, 0x22a, 0x0381);
+       b43_phy_write(dev, 0x22b, 0x0381);
+       b43_phy_write(dev, 0x22c, 0x042b);
+       b43_phy_write(dev, 0x22d, 0x042b);
+       b43_phy_write(dev, 0x22e, 0x0381);
+       b43_phy_write(dev, 0x22f, 0x0381);
 }
 
 static void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev)
@@ -3928,6 +4045,76 @@ int b43_phy_initn(struct b43_wldev *dev)
        return 0;
 }
 
+/* http://bcm-v4.sipsolutions.net/802.11/PmuSpurAvoid */
+static void b43_nphy_pmu_spur_avoid(struct b43_wldev *dev, bool avoid)
+{
+       struct bcma_drv_cc *cc;
+       u32 pmu_ctl;
+
+       switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+       case B43_BUS_BCMA:
+               cc = &dev->dev->bdev->bus->drv_cc;
+               if (dev->dev->chip_id == 43224 || dev->dev->chip_id == 43225) {
+                       if (avoid) {
+                               bcma_chipco_pll_write(cc, 0x0, 0x11500010);
+                               bcma_chipco_pll_write(cc, 0x1, 0x000C0C06);
+                               bcma_chipco_pll_write(cc, 0x2, 0x0F600a08);
+                               bcma_chipco_pll_write(cc, 0x3, 0x00000000);
+                               bcma_chipco_pll_write(cc, 0x4, 0x2001E920);
+                               bcma_chipco_pll_write(cc, 0x5, 0x88888815);
+                       } else {
+                               bcma_chipco_pll_write(cc, 0x0, 0x11100010);
+                               bcma_chipco_pll_write(cc, 0x1, 0x000c0c06);
+                               bcma_chipco_pll_write(cc, 0x2, 0x03000a08);
+                               bcma_chipco_pll_write(cc, 0x3, 0x00000000);
+                               bcma_chipco_pll_write(cc, 0x4, 0x200005c0);
+                               bcma_chipco_pll_write(cc, 0x5, 0x88888815);
+                       }
+                       pmu_ctl = BCMA_CC_PMU_CTL_PLL_UPD;
+               } else if (dev->dev->chip_id == 0x4716) {
+                       if (avoid) {
+                               bcma_chipco_pll_write(cc, 0x0, 0x11500060);
+                               bcma_chipco_pll_write(cc, 0x1, 0x080C0C06);
+                               bcma_chipco_pll_write(cc, 0x2, 0x0F600000);
+                               bcma_chipco_pll_write(cc, 0x3, 0x00000000);
+                               bcma_chipco_pll_write(cc, 0x4, 0x2001E924);
+                               bcma_chipco_pll_write(cc, 0x5, 0x88888815);
+                       } else {
+                               bcma_chipco_pll_write(cc, 0x0, 0x11100060);
+                               bcma_chipco_pll_write(cc, 0x1, 0x080c0c06);
+                               bcma_chipco_pll_write(cc, 0x2, 0x03000000);
+                               bcma_chipco_pll_write(cc, 0x3, 0x00000000);
+                               bcma_chipco_pll_write(cc, 0x4, 0x200005c0);
+                               bcma_chipco_pll_write(cc, 0x5, 0x88888815);
+                       }
+                       pmu_ctl = BCMA_CC_PMU_CTL_PLL_UPD |
+                                 BCMA_CC_PMU_CTL_NOILPONW;
+               } else if (dev->dev->chip_id == 0x4322 ||
+                          dev->dev->chip_id == 0x4340 ||
+                          dev->dev->chip_id == 0x4341) {
+                       bcma_chipco_pll_write(cc, 0x0, 0x11100070);
+                       bcma_chipco_pll_write(cc, 0x1, 0x1014140a);
+                       bcma_chipco_pll_write(cc, 0x5, 0x88888854);
+                       if (avoid)
+                               bcma_chipco_pll_write(cc, 0x2, 0x05201828);
+                       else
+                               bcma_chipco_pll_write(cc, 0x2, 0x05001828);
+                       pmu_ctl = BCMA_CC_PMU_CTL_PLL_UPD;
+               } else {
+                       return;
+               }
+               bcma_cc_set32(cc, BCMA_CC_PMU_CTL, pmu_ctl);
+               break;
+#endif
+#ifdef CONFIG_B43_SSB
+       case B43_BUS_SSB:
+               /* FIXME */
+               break;
+#endif
+       }
+}
+
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ChanspecSetup */
 static void b43_nphy_channel_setup(struct b43_wldev *dev,
                                const struct b43_phy_n_sfo_cfg *e,
@@ -3935,6 +4122,7 @@ static void b43_nphy_channel_setup(struct b43_wldev *dev,
 {
        struct b43_phy *phy = &dev->phy;
        struct b43_phy_n *nphy = dev->phy.n;
+       int ch = new_channel->hw_value;
 
        u16 old_band_5ghz;
        u32 tmp32;
@@ -3974,8 +4162,41 @@ static void b43_nphy_channel_setup(struct b43_wldev *dev,
 
        b43_nphy_tx_lp_fbw(dev);
 
-       if (dev->phy.rev >= 3 && 0) {
-               /* TODO */
+       if (dev->phy.rev >= 3 &&
+           dev->phy.n->spur_avoid != B43_SPUR_AVOID_DISABLE) {
+               bool avoid = false;
+               if (dev->phy.n->spur_avoid == B43_SPUR_AVOID_FORCE) {
+                       avoid = true;
+               } else if (!b43_channel_type_is_40mhz(phy->channel_type)) {
+                       if ((ch >= 5 && ch <= 8) || ch == 13 || ch == 14)
+                               avoid = true;
+               } else { /* 40MHz */
+                       if (nphy->aband_spurwar_en &&
+                           (ch == 38 || ch == 102 || ch == 118))
+                               avoid = dev->dev->chip_id == 0x4716;
+               }
+
+               b43_nphy_pmu_spur_avoid(dev, avoid);
+
+               if (dev->dev->chip_id == 43222 || dev->dev->chip_id == 43224 ||
+                   dev->dev->chip_id == 43225) {
+                       b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW,
+                                   avoid ? 0x5341 : 0x8889);
+                       b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
+               }
+
+               if (dev->phy.rev == 3 || dev->phy.rev == 4)
+                       ; /* TODO: reset PLL */
+
+               if (avoid)
+                       b43_phy_set(dev, B43_NPHY_BBCFG, B43_NPHY_BBCFG_RSTRX);
+               else
+                       b43_phy_mask(dev, B43_NPHY_BBCFG,
+                                    ~B43_NPHY_BBCFG_RSTRX & 0xFFFF);
+
+               b43_nphy_reset_cca(dev);
+
+               /* wl sets useless phy_isspuravoid here */
        }
 
        b43_phy_write(dev, B43_NPHY_NDATAT_DUP40, 0x3830);
@@ -4055,10 +4276,13 @@ static void b43_nphy_op_prepare_structs(struct b43_wldev *dev)
 {
        struct b43_phy *phy = &dev->phy;
        struct b43_phy_n *nphy = phy->n;
+       struct ssb_sprom *sprom = dev->dev->bus_sprom;
 
        memset(nphy, 0, sizeof(*nphy));
 
        nphy->hang_avoid = (phy->rev == 3 || phy->rev == 4);
+       nphy->spur_avoid = (phy->rev >= 3) ?
+                               B43_SPUR_AVOID_AUTO : B43_SPUR_AVOID_DISABLE;
        nphy->gain_boost = true; /* this way we follow wl, assume it is true */
        nphy->txrx_chain = 2; /* sth different than 0 and 1 for now */
        nphy->phyrxchain = 3; /* to avoid b43_nphy_set_rx_core_state like wl */
@@ -4067,6 +4291,38 @@ static void b43_nphy_op_prepare_structs(struct b43_wldev *dev)
         * 0x7f == 127 and we check for 128 when restoring TX pwr ctl. */
        nphy->tx_pwr_idx[0] = 128;
        nphy->tx_pwr_idx[1] = 128;
+
+       /* Hardware TX power control and 5GHz power gain */
+       nphy->txpwrctrl = false;
+       nphy->pwg_gain_5ghz = false;
+       if (dev->phy.rev >= 3 ||
+           (dev->dev->board_vendor == PCI_VENDOR_ID_APPLE &&
+            (dev->dev->core_rev == 11 || dev->dev->core_rev == 12))) {
+               nphy->txpwrctrl = true;
+               nphy->pwg_gain_5ghz = true;
+       } else if (sprom->revision >= 4) {
+               if (dev->phy.rev >= 2 &&
+                   (sprom->boardflags2_lo & B43_BFL2_TXPWRCTRL_EN)) {
+                       nphy->txpwrctrl = true;
+#ifdef CONFIG_B43_SSB
+                       if (dev->dev->bus_type == B43_BUS_SSB &&
+                           dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI) {
+                               struct pci_dev *pdev =
+                                       dev->dev->sdev->bus->host_pci;
+                               if (pdev->device == 0x4328 ||
+                                   pdev->device == 0x432a)
+                                       nphy->pwg_gain_5ghz = true;
+                       }
+#endif
+               } else if (sprom->boardflags2_lo & B43_BFL2_5G_PWRGAIN) {
+                       nphy->pwg_gain_5ghz = true;
+               }
+       }
+
+       if (dev->phy.rev >= 3) {
+               nphy->ipa2g_on = sprom->fem.ghz2.extpa_gain == 2;
+               nphy->ipa5g_on = sprom->fem.ghz5.extpa_gain == 2;
+       }
 }
 
 static void b43_nphy_op_free(struct b43_wldev *dev)
index fbf520285bd1788008b87c6290e7cf0926cf136f..56ef97b5b81576a1029e0a8aaa292fe0eeeeeddd 100644 (file)
 
 struct b43_wldev;
 
+enum b43_nphy_spur_avoid {
+       B43_SPUR_AVOID_DISABLE,
+       B43_SPUR_AVOID_AUTO,
+       B43_SPUR_AVOID_FORCE,
+};
+
 struct b43_chanspec {
        u16 center_freq;
        enum nl80211_channel_type channel_type;
@@ -785,6 +791,7 @@ struct b43_phy_n {
        u16 mphase_txcal_bestcoeffs[11];
 
        bool txpwrctrl;
+       bool pwg_gain_5ghz;
        u8 tx_pwr_idx[2];
        u16 adj_pwr_tbl[84];
        u16 txcal_bbmult;
@@ -803,6 +810,7 @@ struct b43_phy_n {
        u16 classifier_state;
        u16 clip_state[2];
 
+       enum b43_nphy_spur_avoid spur_avoid;
        bool aband_spurwar_en;
        bool gband_spurwar_en;
 
index a01f776ca4de92a0a3b54ff9dfda066d1f05240d..ce037fb6789a483842e37127046d621e29ff5319 100644 (file)
@@ -1572,14 +1572,14 @@ static const struct b2056_inittab_entry b2056_inittab_rev6_syn[] = {
        [B2056_SYN_PLL_XTAL5]           = { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
        [B2056_SYN_PLL_XTAL6]           = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
        [B2056_SYN_PLL_REFDIV]          = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
-       [B2056_SYN_PLL_PFD]             = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+       [B2056_SYN_PLL_PFD]             = { .ghz5 = 0x0006, .ghz2 = 0x0006, UPLOAD, },
        [B2056_SYN_PLL_CP1]             = { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
-       [B2056_SYN_PLL_CP2]             = { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, },
+       [B2056_SYN_PLL_CP2]             = { .ghz5 = 0x003f, .ghz2 = 0x003f, UPLOAD, },
        [B2056_SYN_PLL_CP3]             = { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
-       [B2056_SYN_PLL_LOOPFILTER1]     = { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, },
-       [B2056_SYN_PLL_LOOPFILTER2]     = { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, },
+       [B2056_SYN_PLL_LOOPFILTER1]     = { .ghz5 = 0x0006, .ghz2 = 0x0006, UPLOAD, },
+       [B2056_SYN_PLL_LOOPFILTER2]     = { .ghz5 = 0x0006, .ghz2 = 0x0006, UPLOAD, },
        [B2056_SYN_PLL_LOOPFILTER3]     = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
-       [B2056_SYN_PLL_LOOPFILTER4]     = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+       [B2056_SYN_PLL_LOOPFILTER4]     = { .ghz5 = 0x002b, .ghz2 = 0x002b, UPLOAD, },
        [B2056_SYN_PLL_LOOPFILTER5]     = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
        [B2056_SYN_PLL_MMD1]            = { .ghz5 = 0x001c, .ghz2 = 0x001c, NOUPLOAD, },
        [B2056_SYN_PLL_MMD2]            = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
@@ -9055,6 +9055,21 @@ void b2056_upload_inittabs(struct b43_wldev *dev,
                                B2056_RX1, pts->rx, pts->rx_length);
 }
 
+void b2056_upload_syn_pll_cp2(struct b43_wldev *dev, bool ghz5)
+{
+       struct b2056_inittabs_pts *pts;
+       const struct b2056_inittab_entry *e;
+
+       if (dev->phy.rev >= ARRAY_SIZE(b2056_inittabs)) {
+               B43_WARN_ON(1);
+               return;
+       }
+       pts = &b2056_inittabs[dev->phy.rev];
+       e = &pts->syn[B2056_SYN_PLL_CP2];
+
+       b43_radio_write(dev, B2056_SYN_PLL_CP2, ghz5 ? e->ghz5 : e->ghz2);
+}
+
 const struct b43_nphy_channeltab_entry_rev3 *
 b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq)
 {
index a7159d8578be8d6db37a649dcc04fa8ad6ed849e..5b86673459faa16adbc42105717df7f73d7371e9 100644 (file)
@@ -1090,6 +1090,7 @@ struct b43_nphy_channeltab_entry_rev3 {
 
 void b2056_upload_inittabs(struct b43_wldev *dev,
                           bool ghz5, bool ignore_uploadflag);
+void b2056_upload_syn_pll_cp2(struct b43_wldev *dev, bool ghz5);
 
 /* Get the NPHY Channel Switch Table entry for a channel.
  * Returns NULL on failure to find an entry. */
index 7b326f2efdc9e912e8d47fb6fa3cd6da9e06af62..3252560e9fa157b32e330c43ffeaa9e24c951d62 100644 (file)
@@ -2171,6 +2171,48 @@ static const u16 b43_ntab_loftlt1_r3[] = {
        0x0000, 0x0000,
 };
 
+/* volatile  tables, PHY revision >= 3 */
+
+/* indexed by antswctl2g */
+static const u16 b43_ntab_antswctl2g_r3[4][32] = {
+       {
+               0x0082, 0x0082, 0x0211, 0x0222, 0x0328,
+               0x0000, 0x0000, 0x0000, 0x0144, 0x0000,
+               0x0000, 0x0000, 0x0188, 0x0000, 0x0000,
+               0x0000, 0x0082, 0x0082, 0x0211, 0x0222,
+               0x0328, 0x0000, 0x0000, 0x0000, 0x0144,
+               0x0000, 0x0000, 0x0000, 0x0188, 0x0000,
+               0x0000, 0x0000,
+       },
+       {
+               0x0022, 0x0022, 0x0011, 0x0022, 0x0022,
+               0x0000, 0x0000, 0x0000, 0x0011, 0x0000,
+               0x0000, 0x0000, 0x0022, 0x0000, 0x0000,
+               0x0000, 0x0022, 0x0022, 0x0011, 0x0022,
+               0x0022, 0x0000, 0x0000, 0x0000, 0x0011,
+               0x0000, 0x0000, 0x0000, 0x0022, 0x0000,
+               0x0000, 0x0000,
+       },
+       {
+               0x0088, 0x0088, 0x0044, 0x0088, 0x0088,
+               0x0000, 0x0000, 0x0000, 0x0044, 0x0000,
+               0x0000, 0x0000, 0x0088, 0x0000, 0x0000,
+               0x0000, 0x0088, 0x0088, 0x0044, 0x0088,
+               0x0088, 0x0000, 0x0000, 0x0000, 0x0044,
+               0x0000, 0x0000, 0x0000, 0x0088, 0x0000,
+               0x0000, 0x0000,
+       },
+       {
+               0x0022, 0x0022, 0x0011, 0x0022, 0x0000,
+               0x0000, 0x0000, 0x0000, 0x0011, 0x0000,
+               0x0000, 0x0000, 0x0022, 0x0000, 0x0000,
+               0x03cc, 0x0022, 0x0022, 0x0011, 0x0022,
+               0x0000, 0x0000, 0x0000, 0x0000, 0x0011,
+               0x0000, 0x0000, 0x0000, 0x0022, 0x0000,
+               0x0000, 0x03cc,
+       }
+};
+
 /* TX gain tables */
 const u32 b43_ntab_tx_gain_rev0_1_2[] = {
        0x03cc2b44, 0x03cc2b42, 0x03cc2a44, 0x03cc2a42,
@@ -2652,7 +2694,7 @@ const u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[] = {
 const s16 tbl_tx_filter_coef_rev4[7][15] = {
        {  -377,   137,  -407,   208, -1527,
            956,    93,   186,    93,   230,
-           -44,   230,    20,  -191,   201 },
+           -44,   230,   201,  -191,   201 },
        {   -77,    20,   -98,    49,   -93,
             60,    56,   111,    56,    26,
             -5,    26,    34,   -32,    34 },
@@ -2838,9 +2880,8 @@ u32 b43_ntab_read(struct b43_wldev *dev, u32 offset)
                break;
        case B43_NTAB_32BIT:
                b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset);
-               value = b43_phy_read(dev, B43_NPHY_TABLE_DATAHI);
-               value <<= 16;
-               value |= b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
+               value = b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
+               value |= b43_phy_read(dev, B43_NPHY_TABLE_DATAHI) << 16;
                break;
        default:
                B43_WARN_ON(1);
@@ -2864,6 +2905,12 @@ void b43_ntab_read_bulk(struct b43_wldev *dev, u32 offset,
        b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset);
 
        for (i = 0; i < nr_elements; i++) {
+               /* Auto increment broken + caching issue on BCM43224? */
+               if (dev->dev->chip_id == 43224 && dev->dev->chip_rev == 1) {
+                       b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
+                       b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset + i);
+               }
+
                switch (type) {
                case B43_NTAB_8BIT:
                        *data = b43_phy_read(dev, B43_NPHY_TABLE_DATALO) & 0xFF;
@@ -2874,9 +2921,10 @@ void b43_ntab_read_bulk(struct b43_wldev *dev, u32 offset,
                        data += 2;
                        break;
                case B43_NTAB_32BIT:
-                       *((u32 *)data) = b43_phy_read(dev, B43_NPHY_TABLE_DATAHI);
-                       *((u32 *)data) <<= 16;
-                       *((u32 *)data) |= b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
+                       *((u32 *)data) =
+                               b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
+                       *((u32 *)data) |=
+                               b43_phy_read(dev, B43_NPHY_TABLE_DATAHI) << 16;
                        data += 4;
                        break;
                default:
@@ -2932,6 +2980,13 @@ void b43_ntab_write_bulk(struct b43_wldev *dev, u32 offset,
        b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset);
 
        for (i = 0; i < nr_elements; i++) {
+               /* Auto increment broken + caching issue on BCM43224? */
+               if ((offset >> 10) == 9 && dev->dev->chip_id == 43224 &&
+                   dev->dev->chip_rev == 1) {
+                       b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
+                       b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset + i);
+               }
+
                switch (type) {
                case B43_NTAB_8BIT:
                        value = *data;
@@ -2999,6 +3054,8 @@ void b43_nphy_rev0_1_2_tables_init(struct b43_wldev *dev)
        } while (0)
 void b43_nphy_rev3plus_tables_init(struct b43_wldev *dev)
 {
+       struct ssb_sprom *sprom = dev->dev->bus_sprom;
+
        /* Static tables */
        ntab_upload_r3(dev, B43_NTAB_FRAMESTRUCT_R3, b43_ntab_framestruct_r3);
        ntab_upload_r3(dev, B43_NTAB_PILOT_R3, b43_ntab_pilot_r3);
@@ -3029,7 +3086,11 @@ void b43_nphy_rev3plus_tables_init(struct b43_wldev *dev)
        ntab_upload_r3(dev, B43_NTAB_C1_LOFEEDTH_R3, b43_ntab_loftlt1_r3);
 
        /* Volatile tables */
-       /* TODO */
+       if (sprom->fem.ghz2.antswlut < ARRAY_SIZE(b43_ntab_antswctl2g_r3))
+               ntab_upload_r3(dev, B43_NTAB_ANT_SW_CTL_R3,
+                              b43_ntab_antswctl2g_r3[sprom->fem.ghz2.antswlut]);
+       else
+               B43_WARN_ON(1);
 }
 
 struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent(
index a81696bff0ed9dc88a398be1a4d5e2986fbdbef4..97038c4819304938a6d41fed53ae3b0d65ce5a6c 100644 (file)
@@ -126,26 +126,29 @@ struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent(
 #define B43_NTAB_C1_LOFEEDTH           B43_NTAB16(0x1B, 0x1C0) /* Local Oscillator Feed Through Lookup Table Core 1 */
 #define B43_NTAB_C1_LOFEEDTH_SIZE      128
 
+/* Volatile N-PHY tables, PHY revision >= 3 */
+#define B43_NTAB_ANT_SW_CTL_R3         B43_NTAB16( 9,   0) /* antenna software control */
+
 /* Static N-PHY tables, PHY revision >= 3 */
-#define B43_NTAB_FRAMESTRUCT_R3                B43_NTAB32(10, 000) /* frame struct  */
-#define B43_NTAB_PILOT_R3              B43_NTAB16(11, 000) /* pilot  */
-#define B43_NTAB_TMAP_R3               B43_NTAB32(12, 000) /* TM AP  */
-#define B43_NTAB_INTLEVEL_R3           B43_NTAB32(13, 000) /* INT LV  */
-#define B43_NTAB_TDTRN_R3              B43_NTAB32(14, 000) /* TD TRN  */
-#define B43_NTAB_NOISEVAR0_R3          B43_NTAB32(16, 000) /* noise variance 0  */
+#define B43_NTAB_FRAMESTRUCT_R3                B43_NTAB32(10,   0) /* frame struct  */
+#define B43_NTAB_PILOT_R3              B43_NTAB16(11,   0) /* pilot  */
+#define B43_NTAB_TMAP_R3               B43_NTAB32(12,   0) /* TM AP  */
+#define B43_NTAB_INTLEVEL_R3           B43_NTAB32(13,   0) /* INT LV  */
+#define B43_NTAB_TDTRN_R3              B43_NTAB32(14,   0) /* TD TRN  */
+#define B43_NTAB_NOISEVAR0_R3          B43_NTAB32(16,   0) /* noise variance 0  */
 #define B43_NTAB_NOISEVAR1_R3          B43_NTAB32(16, 128) /* noise variance 1  */
-#define B43_NTAB_MCS_R3                        B43_NTAB16(18, 000) /* MCS  */
+#define B43_NTAB_MCS_R3                        B43_NTAB16(18,   0) /* MCS  */
 #define B43_NTAB_TDI20A0_R3            B43_NTAB32(19, 128) /* TDI 20/0  */
 #define B43_NTAB_TDI20A1_R3            B43_NTAB32(19, 256) /* TDI 20/1  */
 #define B43_NTAB_TDI40A0_R3            B43_NTAB32(19, 640) /* TDI 40/0  */
 #define B43_NTAB_TDI40A1_R3            B43_NTAB32(19, 768) /* TDI 40/1  */
-#define B43_NTAB_PILOTLT_R3            B43_NTAB32(20, 000) /* PLT lookup  */
-#define B43_NTAB_CHANEST_R3            B43_NTAB32(22, 000) /* channel estimate  */
-#define B43_NTAB_FRAMELT_R3            B43_NTAB8 (24, 000) /* frame lookup  */
-#define B43_NTAB_C0_ESTPLT_R3          B43_NTAB8 (26, 000) /* estimated power lookup 0  */
-#define B43_NTAB_C1_ESTPLT_R3          B43_NTAB8 (27, 000) /* estimated power lookup 1  */
-#define B43_NTAB_C0_ADJPLT_R3          B43_NTAB8 (26, 064) /* adjusted power lookup 0  */
-#define B43_NTAB_C1_ADJPLT_R3          B43_NTAB8 (27, 064) /* adjusted power lookup 1  */
+#define B43_NTAB_PILOTLT_R3            B43_NTAB32(20,   0) /* PLT lookup  */
+#define B43_NTAB_CHANEST_R3            B43_NTAB32(22,   0) /* channel estimate  */
+#define B43_NTAB_FRAMELT_R3             B43_NTAB8(24,   0) /* frame lookup  */
+#define B43_NTAB_C0_ESTPLT_R3           B43_NTAB8(26,   0) /* estimated power lookup 0  */
+#define B43_NTAB_C1_ESTPLT_R3           B43_NTAB8(27,   0) /* estimated power lookup 1  */
+#define B43_NTAB_C0_ADJPLT_R3           B43_NTAB8(26,  64) /* adjusted power lookup 0  */
+#define B43_NTAB_C1_ADJPLT_R3           B43_NTAB8(27,  64) /* adjusted power lookup 1  */
 #define B43_NTAB_C0_GAINCTL_R3         B43_NTAB32(26, 192) /* gain control lookup 0  */
 #define B43_NTAB_C1_GAINCTL_R3         B43_NTAB32(27, 192) /* gain control lookup 1  */
 #define B43_NTAB_C0_IQLT_R3            B43_NTAB32(26, 320) /* I/Q lookup 0  */
index 2069fc8f7ad17f50c44d456100dcd4dcf4b63a4e..8f54c2eb68249ae5041773eb746c5d5d3805dd1c 100644 (file)
@@ -3,9 +3,8 @@ config BRCMUTIL
 
 config BRCMSMAC
        tristate "Broadcom IEEE802.11n PCIe SoftMAC WLAN driver"
-       depends on PCI
        depends on MAC80211
-       depends on BCMA=n
+       depends on BCMA
        select BRCMUTIL
        select FW_LOADER
        select CRC_CCITT
index 74933dccf69ee2d3eaa664008fec581f0efa5b33..6c85d668c9d7caf74848193a94501ab3c6a99bd3 100644 (file)
@@ -40,8 +40,7 @@
 
 static void brcmf_sdioh_irqhandler(struct sdio_func *func)
 {
-       struct brcmf_bus *bus_if = dev_get_drvdata(&func->card->dev);
-       struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv;
+       struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev);
 
        brcmf_dbg(TRACE, "***IRQHandler\n");
 
index b416e274c677981a314c43043a928d824f9b8865..b895f198a950c1a8577ef675909b4b427bed92a6 100644 (file)
@@ -40,6 +40,7 @@
 #define DMA_ALIGN_MASK 0x03
 
 #define SDIO_DEVICE_ID_BROADCOM_4329   0x4329
+#define SDIO_DEVICE_ID_BROADCOM_4330   0x4330
 
 #define SDIO_FUNC1_BLOCKSIZE           64
 #define SDIO_FUNC2_BLOCKSIZE           512
@@ -47,6 +48,7 @@
 /* devices we support, null terminated */
 static const struct sdio_device_id brcmf_sdmmc_ids[] = {
        {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)},
+       {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330)},
        { /* end: all zeroes */ },
 };
 MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
@@ -481,12 +483,12 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
                        kfree(bus_if);
                        return -ENOMEM;
                }
-               sdiodev->dev = &func->card->dev;
                sdiodev->func[0] = func->card->sdio_func[0];
                sdiodev->func[1] = func;
+               sdiodev->bus_if = bus_if;
                bus_if->bus_priv = sdiodev;
                bus_if->type = SDIO_BUS;
-               dev_set_drvdata(&func->card->dev, bus_if);
+               dev_set_drvdata(&func->card->dev, sdiodev);
 
                atomic_set(&sdiodev->suspend, false);
                init_waitqueue_head(&sdiodev->request_byte_wait);
@@ -496,12 +498,15 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
        }
 
        if (func->num == 2) {
-               bus_if = dev_get_drvdata(&func->card->dev);
-               sdiodev = bus_if->bus_priv;
+               sdiodev = dev_get_drvdata(&func->card->dev);
                if ((!sdiodev) || (sdiodev->func[1]->card != func->card))
                        return -ENODEV;
                sdiodev->func[2] = func;
 
+               bus_if = sdiodev->bus_if;
+               sdiodev->dev = &func->dev;
+               dev_set_drvdata(&func->dev, bus_if);
+
                brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_probe...\n");
                ret = brcmf_sdio_probe(sdiodev);
        }
@@ -520,11 +525,12 @@ static void brcmf_ops_sdio_remove(struct sdio_func *func)
        brcmf_dbg(INFO, "Function#: 0x%04x\n", func->num);
 
        if (func->num == 2) {
-               bus_if = dev_get_drvdata(&func->card->dev);
+               bus_if = dev_get_drvdata(&func->dev);
                sdiodev = bus_if->bus_priv;
                brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_remove...\n");
                brcmf_sdio_remove(sdiodev);
                dev_set_drvdata(&func->card->dev, NULL);
+               dev_set_drvdata(&func->dev, NULL);
                kfree(bus_if);
                kfree(sdiodev);
        }
@@ -534,15 +540,12 @@ static void brcmf_ops_sdio_remove(struct sdio_func *func)
 static int brcmf_sdio_suspend(struct device *dev)
 {
        mmc_pm_flag_t sdio_flags;
-       struct brcmf_sdio_dev *sdiodev;
        struct sdio_func *func = dev_to_sdio_func(dev);
-       struct brcmf_bus *bus_if = dev_get_drvdata(&func->card->dev);
+       struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev);
        int ret = 0;
 
        brcmf_dbg(TRACE, "\n");
 
-       sdiodev = bus_if->bus_priv;
-
        atomic_set(&sdiodev->suspend, true);
 
        sdio_flags = sdio_get_host_pm_caps(sdiodev->func[1]);
@@ -564,11 +567,9 @@ static int brcmf_sdio_suspend(struct device *dev)
 
 static int brcmf_sdio_resume(struct device *dev)
 {
-       struct brcmf_sdio_dev *sdiodev;
        struct sdio_func *func = dev_to_sdio_func(dev);
-       struct brcmf_bus *bus_if = dev_get_drvdata(&func->card->dev);
+       struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev);
 
-       sdiodev = bus_if->bus_priv;
        brcmf_sdio_wdtmr_enable(sdiodev, true);
        atomic_set(&sdiodev->suspend, false);
        return 0;
index b68d1363105c5ca10aff59c8855aa5fe98214d4e..ed60f4d6962785a598cdb71cc2832e42da28fd16 100644 (file)
@@ -87,7 +87,7 @@
 #define TOE_TX_CSUM_OL         0x00000001
 #define TOE_RX_CSUM_OL         0x00000002
 
-#define        BRCMF_BSS_INFO_VERSION  108 /* curr ver of brcmf_bss_info_le struct */
+#define        BRCMF_BSS_INFO_VERSION  109 /* curr ver of brcmf_bss_info_le struct */
 
 /* size of brcmf_scan_params not including variable length array */
 #define BRCMF_SCAN_PARAMS_FIXED_SIZE 64
index a527d5d4cc4ec98d30108b3352e233a6569309cb..ebd53aa7202bcff86ad480a00ca7a6bbea395ae8 100644 (file)
@@ -58,7 +58,7 @@ struct brcmf_proto_cdc_dcmd {
  * Used on data packets to convey priority across USB.
  */
 #define        BDC_HEADER_LEN          4
-#define BDC_PROTO_VER          1       /* Protocol version */
+#define BDC_PROTO_VER          2       /* Protocol version */
 #define BDC_FLAG_VER_MASK      0xf0    /* Protocol version mask */
 #define BDC_FLAG_VER_SHIFT     4       /* Protocol version shift */
 #define BDC_FLAG_SUM_GOOD      0x04    /* Good RX checksums */
@@ -77,7 +77,7 @@ struct brcmf_proto_bdc_header {
        u8 flags;
        u8 priority;    /* 802.1d Priority, 4:7 flow control info for usb */
        u8 flags2;
-       u8 rssi;
+       u8 data_offset;
 };
 
 
@@ -372,7 +372,7 @@ void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx,
 
        h->priority = (pktbuf->priority & BDC_PRIORITY_MASK);
        h->flags2 = 0;
-       h->rssi = 0;
+       h->data_offset = 0;
        BDC_SET_IF_IDX(h, ifidx);
 }
 
index 18597fe5dfd6971a0820faab0849ba71f5649822..43ba0dd48354ad922261c74120e857ff0da3974a 100644 (file)
@@ -3636,6 +3636,8 @@ static bool brcmf_sdbrcm_chipmatch(u16 chipid)
 {
        if (chipid == BCM4329_CHIP_ID)
                return true;
+       if (chipid == BCM4330_CHIP_ID)
+               return true;
        return false;
 }
 
index f6b1822031fe48862051c40fc79ba62fb9906b85..a6048d78d29409ea6944174eb68ecaa3e3d2b857 100644 (file)
@@ -59,37 +59,17 @@ struct sdiod_drive_str {
        u8 strength;    /* Pad Drive Strength in mA */
        u8 sel;         /* Chip-specific select value */
 };
-/* SDIO Drive Strength to sel value table for PMU Rev 1 */
-static const struct sdiod_drive_str sdiod_drive_strength_tab1[] = {
-       {
-       4, 0x2}, {
-       2, 0x3}, {
-       1, 0x0}, {
-       0, 0x0}
-       };
-/* SDIO Drive Strength to sel value table for PMU Rev 2, 3 */
-static const struct sdiod_drive_str sdiod_drive_strength_tab2[] = {
-       {
-       12, 0x7}, {
-       10, 0x6}, {
-       8, 0x5}, {
-       6, 0x4}, {
-       4, 0x2}, {
-       2, 0x1}, {
-       0, 0x0}
-       };
-/* SDIO Drive Strength to sel value table for PMU Rev 8 (1.8V) */
-static const struct sdiod_drive_str sdiod_drive_strength_tab3[] = {
-       {
-       32, 0x7}, {
-       26, 0x6}, {
-       22, 0x5}, {
-       16, 0x4}, {
-       12, 0x3}, {
-       8, 0x2}, {
-       4, 0x1}, {
-       0, 0x0}
-       };
+/* SDIO Drive Strength to sel value table for PMU Rev 11 (1.8V) */
+static const struct sdiod_drive_str sdiod_drvstr_tab1_1v8[] = {
+       {32, 0x6},
+       {26, 0x7},
+       {22, 0x4},
+       {16, 0x5},
+       {12, 0x2},
+       {8, 0x3},
+       {4, 0x0},
+       {0, 0x1}
+};
 
 u8
 brcmf_sdio_chip_getinfidx(struct chip_info *ci, u16 coreid)
@@ -396,6 +376,23 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
                ci->c_inf[3].base = BCM4329_CORE_ARM_BASE;
                ci->ramsize = BCM4329_RAMSIZE;
                break;
+       case BCM4330_CHIP_ID:
+               ci->c_inf[0].wrapbase = 0x18100000;
+               ci->c_inf[0].cib = 0x27004211;
+               ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
+               ci->c_inf[1].base = 0x18002000;
+               ci->c_inf[1].wrapbase = 0x18102000;
+               ci->c_inf[1].cib = 0x07004211;
+               ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
+               ci->c_inf[2].base = 0x18004000;
+               ci->c_inf[2].wrapbase = 0x18104000;
+               ci->c_inf[2].cib = 0x0d080401;
+               ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
+               ci->c_inf[3].base = 0x18003000;
+               ci->c_inf[3].wrapbase = 0x18103000;
+               ci->c_inf[3].cib = 0x03004211;
+               ci->ramsize = 0x48000;
+               break;
        default:
                brcmf_dbg(ERROR, "chipid 0x%x is not supported\n", ci->chip);
                return -ENODEV;
@@ -569,19 +566,8 @@ brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
                return;
 
        switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) {
-       case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 1):
-               str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab1;
-               str_mask = 0x30000000;
-               str_shift = 28;
-               break;
-       case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 2):
-       case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 3):
-               str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab2;
-               str_mask = 0x00003800;
-               str_shift = 11;
-               break;
-       case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 8):
-               str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab3;
+       case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12):
+               str_tab = (struct sdiod_drive_str *)&sdiod_drvstr_tab1_1v8;
                str_mask = 0x00003800;
                str_shift = 11;
                break;
index c4c2543438ec6e6a73faa930987e2176b966dc08..d36a2a855a6573f538089d07985791c7e5d5922d 100644 (file)
@@ -135,6 +135,7 @@ struct brcmf_sdio_dev {
        wait_queue_head_t request_chain_wait;
        wait_queue_head_t request_buffer_wait;
        struct device *dev;
+       struct brcmf_bus *bus_if;
 };
 
 /* Register/deregister device interrupt handler. */
index 39e305443d7ee7db1081e9cef69d26ab83b9bb9b..ab9bb11abfbb2b26f0bf3a440030a26734099887 100644 (file)
 
 #define        BADIDX          (SI_MAXCORES + 1)
 
-/* Newer chips can access PCI/PCIE and CC core without requiring to change
- * PCI BAR0 WIN
- */
-#define SI_FAST(si) (((si)->pub.buscoretype == PCIE_CORE_ID) ||        \
-                    (((si)->pub.buscoretype == PCI_CORE_ID) && \
-                     (si)->pub.buscorerev >= 13))
-
-#define CCREGS_FAST(si) (((char __iomem *)((si)->curmap) + \
-                         PCI_16KB0_CCREGS_OFFSET))
-
 #define        IS_SIM(chippkg) \
        ((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID))
 
-/*
- * Macros to disable/restore function core(D11, ENET, ILINE20, etc) interrupts
- * before after core switching to avoid invalid register accesss inside ISR.
- */
-#define INTR_OFF(si, intr_val) \
-       if ((si)->intrsoff_fn && \
-           (si)->coreid[(si)->curidx] == (si)->dev_coreid) \
-               intr_val = (*(si)->intrsoff_fn)((si)->intr_arg)
-
-#define INTR_RESTORE(si, intr_val) \
-       if ((si)->intrsrestore_fn && \
-           (si)->coreid[(si)->curidx] == (si)->dev_coreid) \
-               (*(si)->intrsrestore_fn)((si)->intr_arg, intr_val)
+#define PCI(sih)       (ai_get_buscoretype(sih) == PCI_CORE_ID)
+#define PCIE(sih)      (ai_get_buscoretype(sih) == PCIE_CORE_ID)
 
-#define PCI(si)                ((si)->pub.buscoretype == PCI_CORE_ID)
-#define PCIE(si)       ((si)->pub.buscoretype == PCIE_CORE_ID)
-
-#define PCI_FORCEHT(si)        (PCIE(si) && (si->pub.chip == BCM4716_CHIP_ID))
+#define PCI_FORCEHT(sih) (PCIE(sih) && (ai_get_chip_id(sih) == BCM4716_CHIP_ID))
 
 #ifdef BCMDBG
 #define        SI_MSG(fmt, ...)        pr_debug(fmt, ##__VA_ARGS__)
        (((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \
                IS_ALIGNED((x), SI_CORE_SIZE))
 
-#define PCIEREGS(si) ((__iomem char *)((si)->curmap) + \
-                       PCI_16KB0_PCIREGS_OFFSET)
-
 struct aidmp {
        u32 oobselina30;        /* 0x000 */
        u32 oobselina74;        /* 0x004 */
@@ -481,406 +454,13 @@ struct aidmp {
        u32 componentid3;       /* 0xffc */
 };
 
-/* EROM parsing */
-
-static u32
-get_erom_ent(struct si_pub *sih, u32 __iomem **eromptr, u32 mask, u32 match)
-{
-       u32 ent;
-       uint inv = 0, nom = 0;
-
-       while (true) {
-               ent = R_REG(*eromptr);
-               (*eromptr)++;
-
-               if (mask == 0)
-                       break;
-
-               if ((ent & ER_VALID) == 0) {
-                       inv++;
-                       continue;
-               }
-
-               if (ent == (ER_END | ER_VALID))
-                       break;
-
-               if ((ent & mask) == match)
-                       break;
-
-               nom++;
-       }
-
-       return ent;
-}
-
-static u32
-get_asd(struct si_pub *sih, u32 __iomem **eromptr, uint sp, uint ad, uint st,
-       u32 *addrl, u32 *addrh, u32 *sizel, u32 *sizeh)
-{
-       u32 asd, sz, szd;
-
-       asd = get_erom_ent(sih, eromptr, ER_VALID, ER_VALID);
-       if (((asd & ER_TAG1) != ER_ADD) ||
-           (((asd & AD_SP_MASK) >> AD_SP_SHIFT) != sp) ||
-           ((asd & AD_ST_MASK) != st)) {
-               /* This is not what we want, "push" it back */
-               (*eromptr)--;
-               return 0;
-       }
-       *addrl = asd & AD_ADDR_MASK;
-       if (asd & AD_AG32)
-               *addrh = get_erom_ent(sih, eromptr, 0, 0);
-       else
-               *addrh = 0;
-       *sizeh = 0;
-       sz = asd & AD_SZ_MASK;
-       if (sz == AD_SZ_SZD) {
-               szd = get_erom_ent(sih, eromptr, 0, 0);
-               *sizel = szd & SD_SZ_MASK;
-               if (szd & SD_SG32)
-                       *sizeh = get_erom_ent(sih, eromptr, 0, 0);
-       } else
-               *sizel = AD_SZ_BASE << (sz >> AD_SZ_SHIFT);
-
-       return asd;
-}
-
-static void ai_hwfixup(struct si_info *sii)
-{
-}
-
-/* parse the enumeration rom to identify all cores */
-static void ai_scan(struct si_pub *sih, struct chipcregs __iomem *cc)
-{
-       struct si_info *sii = (struct si_info *)sih;
-
-       u32 erombase;
-       u32 __iomem *eromptr, *eromlim;
-       void __iomem *regs = cc;
-
-       erombase = R_REG(&cc->eromptr);
-
-       /* Set wrappers address */
-       sii->curwrap = (void *)((unsigned long)cc + SI_CORE_SIZE);
-
-       /* Now point the window at the erom */
-       pci_write_config_dword(sii->pbus, PCI_BAR0_WIN, erombase);
-       eromptr = regs;
-       eromlim = eromptr + (ER_REMAPCONTROL / sizeof(u32));
-
-       while (eromptr < eromlim) {
-               u32 cia, cib, cid, mfg, crev, nmw, nsw, nmp, nsp;
-               u32 mpd, asd, addrl, addrh, sizel, sizeh;
-               u32 __iomem *base;
-               uint i, j, idx;
-               bool br;
-
-               br = false;
-
-               /* Grok a component */
-               cia = get_erom_ent(sih, &eromptr, ER_TAG, ER_CI);
-               if (cia == (ER_END | ER_VALID)) {
-                       /*  Found END of erom */
-                       ai_hwfixup(sii);
-                       return;
-               }
-               base = eromptr - 1;
-               cib = get_erom_ent(sih, &eromptr, 0, 0);
-
-               if ((cib & ER_TAG) != ER_CI) {
-                       /* CIA not followed by CIB */
-                       goto error;
-               }
-
-               cid = (cia & CIA_CID_MASK) >> CIA_CID_SHIFT;
-               mfg = (cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT;
-               crev = (cib & CIB_REV_MASK) >> CIB_REV_SHIFT;
-               nmw = (cib & CIB_NMW_MASK) >> CIB_NMW_SHIFT;
-               nsw = (cib & CIB_NSW_MASK) >> CIB_NSW_SHIFT;
-               nmp = (cib & CIB_NMP_MASK) >> CIB_NMP_SHIFT;
-               nsp = (cib & CIB_NSP_MASK) >> CIB_NSP_SHIFT;
-
-               if (((mfg == MFGID_ARM) && (cid == DEF_AI_COMP)) || (nsp == 0))
-                       continue;
-               if ((nmw + nsw == 0)) {
-                       /* A component which is not a core */
-                       if (cid == OOB_ROUTER_CORE_ID) {
-                               asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE,
-                                             &addrl, &addrh, &sizel, &sizeh);
-                               if (asd != 0)
-                                       sii->oob_router = addrl;
-                       }
-                       continue;
-               }
-
-               idx = sii->numcores;
-/*             sii->eromptr[idx] = base; */
-               sii->cia[idx] = cia;
-               sii->cib[idx] = cib;
-               sii->coreid[idx] = cid;
-
-               for (i = 0; i < nmp; i++) {
-                       mpd = get_erom_ent(sih, &eromptr, ER_VALID, ER_VALID);
-                       if ((mpd & ER_TAG) != ER_MP) {
-                               /* Not enough MP entries for component */
-                               goto error;
-                       }
-               }
-
-               /* First Slave Address Descriptor should be port 0:
-                * the main register space for the core
-                */
-               asd =
-                   get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, &addrl, &addrh,
-                           &sizel, &sizeh);
-               if (asd == 0) {
-                       /* Try again to see if it is a bridge */
-                       asd =
-                           get_asd(sih, &eromptr, 0, 0, AD_ST_BRIDGE, &addrl,
-                                   &addrh, &sizel, &sizeh);
-                       if (asd != 0)
-                               br = true;
-                       else if ((addrh != 0) || (sizeh != 0)
-                                || (sizel != SI_CORE_SIZE)) {
-                               /* First Slave ASD for core malformed */
-                               goto error;
-                       }
-               }
-               sii->coresba[idx] = addrl;
-               sii->coresba_size[idx] = sizel;
-               /* Get any more ASDs in port 0 */
-               j = 1;
-               do {
-                       asd =
-                           get_asd(sih, &eromptr, 0, j, AD_ST_SLAVE, &addrl,
-                                   &addrh, &sizel, &sizeh);
-                       if ((asd != 0) && (j == 1) && (sizel == SI_CORE_SIZE)) {
-                               sii->coresba2[idx] = addrl;
-                               sii->coresba2_size[idx] = sizel;
-                       }
-                       j++;
-               } while (asd != 0);
-
-               /* Go through the ASDs for other slave ports */
-               for (i = 1; i < nsp; i++) {
-                       j = 0;
-                       do {
-                               asd =
-                                   get_asd(sih, &eromptr, i, j++, AD_ST_SLAVE,
-                                           &addrl, &addrh, &sizel, &sizeh);
-                       } while (asd != 0);
-                       if (j == 0) {
-                               /* SP has no address descriptors */
-                               goto error;
-                       }
-               }
-
-               /* Now get master wrappers */
-               for (i = 0; i < nmw; i++) {
-                       asd =
-                           get_asd(sih, &eromptr, i, 0, AD_ST_MWRAP, &addrl,
-                                   &addrh, &sizel, &sizeh);
-                       if (asd == 0) {
-                               /* Missing descriptor for MW */
-                               goto error;
-                       }
-                       if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) {
-                               /* Master wrapper %d is not 4KB */
-                               goto error;
-                       }
-                       if (i == 0)
-                               sii->wrapba[idx] = addrl;
-               }
-
-               /* And finally slave wrappers */
-               for (i = 0; i < nsw; i++) {
-                       uint fwp = (nsp == 1) ? 0 : 1;
-                       asd =
-                           get_asd(sih, &eromptr, fwp + i, 0, AD_ST_SWRAP,
-                                   &addrl, &addrh, &sizel, &sizeh);
-                       if (asd == 0) {
-                               /* Missing descriptor for SW */
-                               goto error;
-                       }
-                       if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) {
-                               /* Slave wrapper is not 4KB */
-                               goto error;
-                       }
-                       if ((nmw == 0) && (i == 0))
-                               sii->wrapba[idx] = addrl;
-               }
-
-               /* Don't record bridges */
-               if (br)
-                       continue;
-
-               /* Done with core */
-               sii->numcores++;
-       }
-
- error:
-       /* Reached end of erom without finding END */
-       sii->numcores = 0;
-       return;
-}
-
-/*
- * This function changes the logical "focus" to the indicated core.
- * Return the current core's virtual address. Since each core starts with the
- * same set of registers (BIST, clock control, etc), the returned address
- * contains the first register of this 'common' register block (not to be
- * confused with 'common core').
- */
-void __iomem *ai_setcoreidx(struct si_pub *sih, uint coreidx)
-{
-       struct si_info *sii = (struct si_info *)sih;
-       u32 addr = sii->coresba[coreidx];
-       u32 wrap = sii->wrapba[coreidx];
-
-       if (coreidx >= sii->numcores)
-               return NULL;
-
-       /* point bar0 window */
-       pci_write_config_dword(sii->pbus, PCI_BAR0_WIN, addr);
-       /* point bar0 2nd 4KB window */
-       pci_write_config_dword(sii->pbus, PCI_BAR0_WIN2, wrap);
-       sii->curidx = coreidx;
-
-       return sii->curmap;
-}
-
-/* Return the number of address spaces in current core */
-int ai_numaddrspaces(struct si_pub *sih)
-{
-       return 2;
-}
-
-/* Return the address of the nth address space in the current core */
-u32 ai_addrspace(struct si_pub *sih, uint asidx)
-{
-       struct si_info *sii;
-       uint cidx;
-
-       sii = (struct si_info *)sih;
-       cidx = sii->curidx;
-
-       if (asidx == 0)
-               return sii->coresba[cidx];
-       else if (asidx == 1)
-               return sii->coresba2[cidx];
-       else {
-               /* Need to parse the erom again to find addr space */
-               return 0;
-       }
-}
-
-/* Return the size of the nth address space in the current core */
-u32 ai_addrspacesize(struct si_pub *sih, uint asidx)
-{
-       struct si_info *sii;
-       uint cidx;
-
-       sii = (struct si_info *)sih;
-       cidx = sii->curidx;
-
-       if (asidx == 0)
-               return sii->coresba_size[cidx];
-       else if (asidx == 1)
-               return sii->coresba2_size[cidx];
-       else {
-               /* Need to parse the erom again to find addr */
-               return 0;
-       }
-}
-
-uint ai_flag(struct si_pub *sih)
-{
-       struct si_info *sii;
-       struct aidmp *ai;
-
-       sii = (struct si_info *)sih;
-       ai = sii->curwrap;
-
-       return R_REG(&ai->oobselouta30) & 0x1f;
-}
-
-void ai_setint(struct si_pub *sih, int siflag)
-{
-}
-
-uint ai_corevendor(struct si_pub *sih)
-{
-       struct si_info *sii;
-       u32 cia;
-
-       sii = (struct si_info *)sih;
-       cia = sii->cia[sii->curidx];
-       return (cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT;
-}
-
-uint ai_corerev(struct si_pub *sih)
-{
-       struct si_info *sii;
-       u32 cib;
-
-       sii = (struct si_info *)sih;
-       cib = sii->cib[sii->curidx];
-       return (cib & CIB_REV_MASK) >> CIB_REV_SHIFT;
-}
-
-bool ai_iscoreup(struct si_pub *sih)
-{
-       struct si_info *sii;
-       struct aidmp *ai;
-
-       sii = (struct si_info *)sih;
-       ai = sii->curwrap;
-
-       return (((R_REG(&ai->ioctrl) & (SICF_FGC | SICF_CLOCK_EN)) ==
-                SICF_CLOCK_EN)
-               && ((R_REG(&ai->resetctrl) & AIRC_RESET) == 0));
-}
-
-void ai_core_cflags_wo(struct si_pub *sih, u32 mask, u32 val)
-{
-       struct si_info *sii;
-       struct aidmp *ai;
-       u32 w;
-
-       sii = (struct si_info *)sih;
-
-       ai = sii->curwrap;
-
-       if (mask || val) {
-               w = ((R_REG(&ai->ioctrl) & ~mask) | val);
-               W_REG(&ai->ioctrl, w);
-       }
-}
-
-u32 ai_core_cflags(struct si_pub *sih, u32 mask, u32 val)
-{
-       struct si_info *sii;
-       struct aidmp *ai;
-       u32 w;
-
-       sii = (struct si_info *)sih;
-       ai = sii->curwrap;
-
-       if (mask || val) {
-               w = ((R_REG(&ai->ioctrl) & ~mask) | val);
-               W_REG(&ai->ioctrl, w);
-       }
-
-       return R_REG(&ai->ioctrl);
-}
-
 /* return true if PCIE capability exists in the pci config space */
 static bool ai_ispcie(struct si_info *sii)
 {
        u8 cap_ptr;
 
        cap_ptr =
-           pcicore_find_pci_capability(sii->pbus, PCI_CAP_ID_EXP, NULL,
+           pcicore_find_pci_capability(sii->pcibus, PCI_CAP_ID_EXP, NULL,
                                        NULL);
        if (!cap_ptr)
                return false;
@@ -896,117 +476,69 @@ static bool ai_buscore_prep(struct si_info *sii)
        return true;
 }
 
-u32 ai_core_sflags(struct si_pub *sih, u32 mask, u32 val)
-{
-       struct si_info *sii;
-       struct aidmp *ai;
-       u32 w;
-
-       sii = (struct si_info *)sih;
-       ai = sii->curwrap;
-
-       if (mask || val) {
-               w = ((R_REG(&ai->iostatus) & ~mask) | val);
-               W_REG(&ai->iostatus, w);
-       }
-
-       return R_REG(&ai->iostatus);
-}
-
 static bool
-ai_buscore_setup(struct si_info *sii, u32 savewin, uint *origidx)
+ai_buscore_setup(struct si_info *sii, struct bcma_device *cc)
 {
-       bool pci, pcie;
-       uint i;
-       uint pciidx, pcieidx, pcirev, pcierev;
-       struct chipcregs __iomem *cc;
+       struct bcma_device *pci = NULL;
+       struct bcma_device *pcie = NULL;
+       struct bcma_device *core;
 
-       cc = ai_setcoreidx(&sii->pub, SI_CC_IDX);
+
+       /* no cores found, bail out */
+       if (cc->bus->nr_cores == 0)
+               return false;
 
        /* get chipcommon rev */
-       sii->pub.ccrev = (int)ai_corerev(&sii->pub);
+       sii->pub.ccrev = cc->id.rev;
 
        /* get chipcommon chipstatus */
-       if (sii->pub.ccrev >= 11)
-               sii->pub.chipst = R_REG(&cc->chipstatus);
+       if (ai_get_ccrev(&sii->pub) >= 11)
+               sii->chipst = bcma_read32(cc, CHIPCREGOFFS(chipstatus));
 
        /* get chipcommon capabilites */
-       sii->pub.cccaps = R_REG(&cc->capabilities);
-       /* get chipcommon extended capabilities */
-
-       if (sii->pub.ccrev >= 35)
-               sii->pub.cccaps_ext = R_REG(&cc->capabilities_ext);
+       sii->pub.cccaps = bcma_read32(cc, CHIPCREGOFFS(capabilities));
 
        /* get pmu rev and caps */
-       if (sii->pub.cccaps & CC_CAP_PMU) {
-               sii->pub.pmucaps = R_REG(&cc->pmucapabilities);
+       if (ai_get_cccaps(&sii->pub) & CC_CAP_PMU) {
+               sii->pub.pmucaps = bcma_read32(cc,
+                                              CHIPCREGOFFS(pmucapabilities));
                sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK;
        }
 
-       /* figure out bus/orignal core idx */
-       sii->pub.buscoretype = NODEV_CORE_ID;
-       sii->pub.buscorerev = NOREV;
-       sii->pub.buscoreidx = BADIDX;
-
-       pci = pcie = false;
-       pcirev = pcierev = NOREV;
-       pciidx = pcieidx = BADIDX;
-
-       for (i = 0; i < sii->numcores; i++) {
+       /* figure out buscore */
+       list_for_each_entry(core, &cc->bus->cores, list) {
                uint cid, crev;
 
-               ai_setcoreidx(&sii->pub, i);
-               cid = ai_coreid(&sii->pub);
-               crev = ai_corerev(&sii->pub);
+               cid = core->id.id;
+               crev = core->id.rev;
 
                if (cid == PCI_CORE_ID) {
-                       pciidx = i;
-                       pcirev = crev;
-                       pci = true;
+                       pci = core;
                } else if (cid == PCIE_CORE_ID) {
-                       pcieidx = i;
-                       pcierev = crev;
-                       pcie = true;
+                       pcie = core;
                }
-
-               /* find the core idx before entering this func. */
-               if ((savewin && (savewin == sii->coresba[i])) ||
-                   (cc == sii->regs[i]))
-                       *origidx = i;
        }
 
        if (pci && pcie) {
                if (ai_ispcie(sii))
-                       pci = false;
+                       pci = NULL;
                else
-                       pcie = false;
+                       pcie = NULL;
        }
        if (pci) {
-               sii->pub.buscoretype = PCI_CORE_ID;
-               sii->pub.buscorerev = pcirev;
-               sii->pub.buscoreidx = pciidx;
+               sii->buscore = pci;
        } else if (pcie) {
-               sii->pub.buscoretype = PCIE_CORE_ID;
-               sii->pub.buscorerev = pcierev;
-               sii->pub.buscoreidx = pcieidx;
+               sii->buscore = pcie;
        }
 
        /* fixup necessary chip/core configurations */
-       if (SI_FAST(sii)) {
-               if (!sii->pch) {
-                       sii->pch = pcicore_init(&sii->pub, sii->pbus,
-                                               (__iomem void *)PCIEREGS(sii));
-                       if (sii->pch == NULL)
-                               return false;
-               }
+       if (!sii->pch) {
+               sii->pch = pcicore_init(&sii->pub, sii->icbus->drv_pci.core);
+               if (sii->pch == NULL)
+                       return false;
        }
-       if (ai_pci_fixcfg(&sii->pub)) {
-               /* si_doattach: si_pci_fixcfg failed */
+       if (ai_pci_fixcfg(&sii->pub))
                return false;
-       }
-
-       /* return to the original core */
-       ai_setcoreidx(&sii->pub, *origidx);
 
        return true;
 }
@@ -1019,39 +551,27 @@ static __used void ai_nvram_process(struct si_info *sii)
        uint w = 0;
 
        /* do a pci config read to get subsystem id and subvendor id */
-       pci_read_config_dword(sii->pbus, PCI_SUBSYSTEM_VENDOR_ID, &w);
+       pci_read_config_dword(sii->pcibus, PCI_SUBSYSTEM_VENDOR_ID, &w);
 
        sii->pub.boardvendor = w & 0xffff;
        sii->pub.boardtype = (w >> 16) & 0xffff;
-       sii->pub.boardflags = getintvar(&sii->pub, BRCMS_SROM_BOARDFLAGS);
 }
 
 static struct si_info *ai_doattach(struct si_info *sii,
-                                  void __iomem *regs, struct pci_dev *pbus)
+                                  struct bcma_bus *pbus)
 {
        struct si_pub *sih = &sii->pub;
        u32 w, savewin;
-       struct chipcregs __iomem *cc;
+       struct bcma_device *cc;
        uint socitype;
-       uint origidx;
-
-       memset((unsigned char *) sii, 0, sizeof(struct si_info));
 
        savewin = 0;
 
-       sih->buscoreidx = BADIDX;
-
-       sii->curmap = regs;
-       sii->pbus = pbus;
+       sii->icbus = pbus;
+       sii->pcibus = pbus->host_pci;
 
-       /* find Chipcommon address */
-       pci_read_config_dword(sii->pbus, PCI_BAR0_WIN, &savewin);
-       if (!GOODCOREADDR(savewin, SI_ENUM_BASE))
-               savewin = SI_ENUM_BASE;
-
-       pci_write_config_dword(sii->pbus, PCI_BAR0_WIN,
-                              SI_ENUM_BASE);
-       cc = (struct chipcregs __iomem *) regs;
+       /* switch to Chipcommon core */
+       cc = pbus->drv_cc.core;
 
        /* bus/core/clk setup for register access */
        if (!ai_buscore_prep(sii))
@@ -1064,89 +584,69 @@ static struct si_info *ai_doattach(struct si_info *sii,
         *   hosts w/o chipcommon), some way of recognizing them needs to
         *   be added here.
         */
-       w = R_REG(&cc->chipid);
+       w = bcma_read32(cc, CHIPCREGOFFS(chipid));
        socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
        /* Might as wll fill in chip id rev & pkg */
        sih->chip = w & CID_ID_MASK;
        sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT;
        sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT;
 
-       sih->issim = false;
-
        /* scan for cores */
-       if (socitype == SOCI_AI) {
-               SI_MSG("Found chip type AI (0x%08x)\n", w);
-               /* pass chipc address instead of original core base */
-               ai_scan(&sii->pub, cc);
-       } else {
-               /* Found chip of unknown type */
-               return NULL;
-       }
-       /* no cores found, bail out */
-       if (sii->numcores == 0)
+       if (socitype != SOCI_AI)
                return NULL;
 
-       /* bus/core/clk setup */
-       origidx = SI_CC_IDX;
-       if (!ai_buscore_setup(sii, savewin, &origidx))
+       SI_MSG("Found chip type AI (0x%08x)\n", w);
+       if (!ai_buscore_setup(sii, cc))
                goto exit;
 
        /* Init nvram from sprom/otp if they exist */
-       if (srom_var_init(&sii->pub, cc))
+       if (srom_var_init(&sii->pub))
                goto exit;
 
        ai_nvram_process(sii);
 
        /* === NVRAM, clock is ready === */
-       cc = (struct chipcregs __iomem *) ai_setcore(sih, CC_CORE_ID, 0);
-       W_REG(&cc->gpiopullup, 0);
-       W_REG(&cc->gpiopulldown, 0);
-       ai_setcoreidx(sih, origidx);
+       bcma_write32(cc, CHIPCREGOFFS(gpiopullup), 0);
+       bcma_write32(cc, CHIPCREGOFFS(gpiopulldown), 0);
 
        /* PMU specific initializations */
-       if (sih->cccaps & CC_CAP_PMU) {
-               u32 xtalfreq;
+       if (ai_get_cccaps(sih) & CC_CAP_PMU) {
                si_pmu_init(sih);
-               si_pmu_chip_init(sih);
-
-               xtalfreq = si_pmu_measure_alpclk(sih);
-               si_pmu_pll_init(sih, xtalfreq);
+               (void)si_pmu_measure_alpclk(sih);
                si_pmu_res_init(sih);
-               si_pmu_swreg_init(sih);
        }
 
        /* setup the GPIO based LED powersave register */
        w = getintvar(sih, BRCMS_SROM_LEDDC);
        if (w == 0)
                w = DEFAULT_GPIOTIMERVAL;
-       ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, gpiotimerval),
-                  ~0, w);
+       ai_cc_reg(sih, offsetof(struct chipcregs, gpiotimerval),
+                 ~0, w);
 
-       if (PCIE(sii))
+       if (PCIE(sih))
                pcicore_attach(sii->pch, SI_DOATTACH);
 
-       if (sih->chip == BCM43224_CHIP_ID) {
+       if (ai_get_chip_id(sih) == BCM43224_CHIP_ID) {
                /*
                 * enable 12 mA drive strenth for 43224 and
                 * set chipControl register bit 15
                 */
-               if (sih->chiprev == 0) {
+               if (ai_get_chiprev(sih) == 0) {
                        SI_MSG("Applying 43224A0 WARs\n");
-                       ai_corereg(sih, SI_CC_IDX,
-                                  offsetof(struct chipcregs, chipcontrol),
-                                  CCTRL43224_GPIO_TOGGLE,
-                                  CCTRL43224_GPIO_TOGGLE);
+                       ai_cc_reg(sih, offsetof(struct chipcregs, chipcontrol),
+                                 CCTRL43224_GPIO_TOGGLE,
+                                 CCTRL43224_GPIO_TOGGLE);
                        si_pmu_chipcontrol(sih, 0, CCTRL_43224A0_12MA_LED_DRIVE,
                                           CCTRL_43224A0_12MA_LED_DRIVE);
                }
-               if (sih->chiprev >= 1) {
+               if (ai_get_chiprev(sih) >= 1) {
                        SI_MSG("Applying 43224B0+ WARs\n");
                        si_pmu_chipcontrol(sih, 0, CCTRL_43224B0_12MA_LED_DRIVE,
                                           CCTRL_43224B0_12MA_LED_DRIVE);
                }
        }
 
-       if (sih->chip == BCM4313_CHIP_ID) {
+       if (ai_get_chip_id(sih) == BCM4313_CHIP_ID) {
                /*
                 * enable 12 mA drive strenth for 4313 and
                 * set chipControl register bit 1
@@ -1167,22 +667,19 @@ static struct si_info *ai_doattach(struct si_info *sii,
 }
 
 /*
- * Allocate a si handle.
- * devid - pci device id (used to determine chip#)
- * osh - opaque OS handle
- * regs - virtual address of initial core registers
+ * Allocate a si handle and do the attach.
  */
 struct si_pub *
-ai_attach(void __iomem *regs, struct pci_dev *sdh)
+ai_attach(struct bcma_bus *pbus)
 {
        struct si_info *sii;
 
        /* alloc struct si_info */
-       sii = kmalloc(sizeof(struct si_info), GFP_ATOMIC);
+       sii = kzalloc(sizeof(struct si_info), GFP_ATOMIC);
        if (sii == NULL)
                return NULL;
 
-       if (ai_doattach(sii, regs, sdh) == NULL) {
+       if (ai_doattach(sii, pbus) == NULL) {
                kfree(sii);
                return NULL;
        }
@@ -1211,292 +708,66 @@ void ai_detach(struct si_pub *sih)
        kfree(sii);
 }
 
-/* register driver interrupt disabling and restoring callback functions */
-void
-ai_register_intr_callback(struct si_pub *sih, void *intrsoff_fn,
-                         void *intrsrestore_fn,
-                         void *intrsenabled_fn, void *intr_arg)
-{
-       struct si_info *sii;
-
-       sii = (struct si_info *)sih;
-       sii->intr_arg = intr_arg;
-       sii->intrsoff_fn = (u32 (*)(void *)) intrsoff_fn;
-       sii->intrsrestore_fn = (void (*) (void *, u32)) intrsrestore_fn;
-       sii->intrsenabled_fn = (bool (*)(void *)) intrsenabled_fn;
-       /* save current core id.  when this function called, the current core
-        * must be the core which provides driver functions(il, et, wl, etc.)
-        */
-       sii->dev_coreid = sii->coreid[sii->curidx];
-}
-
-void ai_deregister_intr_callback(struct si_pub *sih)
-{
-       struct si_info *sii;
-
-       sii = (struct si_info *)sih;
-       sii->intrsoff_fn = NULL;
-}
-
-uint ai_coreid(struct si_pub *sih)
-{
-       struct si_info *sii;
-
-       sii = (struct si_info *)sih;
-       return sii->coreid[sii->curidx];
-}
-
-uint ai_coreidx(struct si_pub *sih)
-{
-       struct si_info *sii;
-
-       sii = (struct si_info *)sih;
-       return sii->curidx;
-}
-
-bool ai_backplane64(struct si_pub *sih)
-{
-       return (sih->cccaps & CC_CAP_BKPLN64) != 0;
-}
-
 /* return index of coreid or BADIDX if not found */
-uint ai_findcoreidx(struct si_pub *sih, uint coreid, uint coreunit)
+struct bcma_device *ai_findcore(struct si_pub *sih, u16 coreid, u16 coreunit)
 {
+       struct bcma_device *core;
        struct si_info *sii;
        uint found;
-       uint i;
 
        sii = (struct si_info *)sih;
 
        found = 0;
 
-       for (i = 0; i < sii->numcores; i++)
-               if (sii->coreid[i] == coreid) {
+       list_for_each_entry(core, &sii->icbus->cores, list)
+               if (core->id.id == coreid) {
                        if (found == coreunit)
-                               return i;
+                               return core;
                        found++;
                }
 
-       return BADIDX;
-}
-
-/*
- * This function changes logical "focus" to the indicated core;
- * must be called with interrupts off.
- * Moreover, callers should keep interrupts off during switching
- * out of and back to d11 core.
- */
-void __iomem *ai_setcore(struct si_pub *sih, uint coreid, uint coreunit)
-{
-       uint idx;
-
-       idx = ai_findcoreidx(sih, coreid, coreunit);
-       if (idx >= SI_MAXCORES)
-               return NULL;
-
-       return ai_setcoreidx(sih, idx);
-}
-
-/* Turn off interrupt as required by ai_setcore, before switch core */
-void __iomem *ai_switch_core(struct si_pub *sih, uint coreid, uint *origidx,
-                            uint *intr_val)
-{
-       void __iomem *cc;
-       struct si_info *sii;
-
-       sii = (struct si_info *)sih;
-
-       if (SI_FAST(sii)) {
-               /* Overloading the origidx variable to remember the coreid,
-                * this works because the core ids cannot be confused with
-                * core indices.
-                */
-               *origidx = coreid;
-               if (coreid == CC_CORE_ID)
-                       return CCREGS_FAST(sii);
-               else if (coreid == sih->buscoretype)
-                       return PCIEREGS(sii);
-       }
-       INTR_OFF(sii, *intr_val);
-       *origidx = sii->curidx;
-       cc = ai_setcore(sih, coreid, 0);
-       return cc;
-}
-
-/* restore coreidx and restore interrupt */
-void ai_restore_core(struct si_pub *sih, uint coreid, uint intr_val)
-{
-       struct si_info *sii;
-
-       sii = (struct si_info *)sih;
-       if (SI_FAST(sii)
-           && ((coreid == CC_CORE_ID) || (coreid == sih->buscoretype)))
-               return;
-
-       ai_setcoreidx(sih, coreid);
-       INTR_RESTORE(sii, intr_val);
-}
-
-void ai_write_wrapperreg(struct si_pub *sih, u32 offset, u32 val)
-{
-       struct si_info *sii = (struct si_info *)sih;
-       u32 *w = (u32 *) sii->curwrap;
-       W_REG(w + (offset / 4), val);
-       return;
+       return NULL;
 }
 
 /*
- * Switch to 'coreidx', issue a single arbitrary 32bit register mask&set
- * operation, switch back to the original core, and return the new value.
- *
- * When using the silicon backplane, no fiddling with interrupts or core
- * switches is needed.
- *
- * Also, when using pci/pcie, we can optimize away the core switching for pci
- * registers and (on newer pci cores) chipcommon registers.
+ * read/modify chipcommon core register.
  */
-uint ai_corereg(struct si_pub *sih, uint coreidx, uint regoff, uint mask,
-               uint val)
+uint ai_cc_reg(struct si_pub *sih, uint regoff, u32 mask, u32 val)
 {
-       uint origidx = 0;
-       u32 __iomem *r = NULL;
-       uint w;
-       uint intr_val = 0;
-       bool fast = false;
+       struct bcma_device *cc;
+       u32 w;
        struct si_info *sii;
 
        sii = (struct si_info *)sih;
-
-       if (coreidx >= SI_MAXCORES)
-               return 0;
-
-       /*
-        * If pci/pcie, we can get at pci/pcie regs
-        * and on newer cores to chipc
-        */
-       if ((sii->coreid[coreidx] == CC_CORE_ID) && SI_FAST(sii)) {
-               /* Chipc registers are mapped at 12KB */
-               fast = true;
-               r = (u32 __iomem *)((__iomem char *)sii->curmap +
-                                   PCI_16KB0_CCREGS_OFFSET + regoff);
-       } else if (sii->pub.buscoreidx == coreidx) {
-               /*
-                * pci registers are at either in the last 2KB of
-                * an 8KB window or, in pcie and pci rev 13 at 8KB
-                */
-               fast = true;
-               if (SI_FAST(sii))
-                       r = (u32 __iomem *)((__iomem char *)sii->curmap +
-                                   PCI_16KB0_PCIREGS_OFFSET + regoff);
-               else
-                       r = (u32 __iomem *)((__iomem char *)sii->curmap +
-                                   ((regoff >= SBCONFIGOFF) ?
-                                     PCI_BAR0_PCISBR_OFFSET :
-                                     PCI_BAR0_PCIREGS_OFFSET) + regoff);
-       }
-
-       if (!fast) {
-               INTR_OFF(sii, intr_val);
-
-               /* save current core index */
-               origidx = ai_coreidx(&sii->pub);
-
-               /* switch core */
-               r = (u32 __iomem *) ((unsigned char __iomem *)
-                       ai_setcoreidx(&sii->pub, coreidx) + regoff);
-       }
+       cc = sii->icbus->drv_cc.core;
 
        /* mask and set */
        if (mask || val) {
-               w = (R_REG(r) & ~mask) | val;
-               W_REG(r, w);
+               bcma_maskset32(cc, regoff, ~mask, val);
        }
 
        /* readback */
-       w = R_REG(r);
-
-       if (!fast) {
-               /* restore core index */
-               if (origidx != coreidx)
-                       ai_setcoreidx(&sii->pub, origidx);
-
-               INTR_RESTORE(sii, intr_val);
-       }
+       w = bcma_read32(cc, regoff);
 
        return w;
 }
 
-void ai_core_disable(struct si_pub *sih, u32 bits)
-{
-       struct si_info *sii;
-       u32 dummy;
-       struct aidmp *ai;
-
-       sii = (struct si_info *)sih;
-
-       ai = sii->curwrap;
-
-       /* if core is already in reset, just return */
-       if (R_REG(&ai->resetctrl) & AIRC_RESET)
-               return;
-
-       W_REG(&ai->ioctrl, bits);
-       dummy = R_REG(&ai->ioctrl);
-       udelay(10);
-
-       W_REG(&ai->resetctrl, AIRC_RESET);
-       udelay(1);
-}
-
-/* reset and re-enable a core
- * inputs:
- * bits - core specific bits that are set during and after reset sequence
- * resetbits - core specific bits that are set only during reset sequence
- */
-void ai_core_reset(struct si_pub *sih, u32 bits, u32 resetbits)
-{
-       struct si_info *sii;
-       struct aidmp *ai;
-       u32 dummy;
-
-       sii = (struct si_info *)sih;
-       ai = sii->curwrap;
-
-       /*
-        * Must do the disable sequence first to work
-        * for arbitrary current core state.
-        */
-       ai_core_disable(sih, (bits | resetbits));
-
-       /*
-        * Now do the initialization sequence.
-        */
-       W_REG(&ai->ioctrl, (bits | SICF_FGC | SICF_CLOCK_EN));
-       dummy = R_REG(&ai->ioctrl);
-       W_REG(&ai->resetctrl, 0);
-       udelay(1);
-
-       W_REG(&ai->ioctrl, (bits | SICF_CLOCK_EN));
-       dummy = R_REG(&ai->ioctrl);
-       udelay(1);
-}
-
 /* return the slow clock source - LPO, XTAL, or PCI */
-static uint ai_slowclk_src(struct si_info *sii)
+static uint ai_slowclk_src(struct si_pub *sih, struct bcma_device *cc)
 {
-       struct chipcregs __iomem *cc;
+       struct si_info *sii;
        u32 val;
 
-       if (sii->pub.ccrev < 6) {
-               pci_read_config_dword(sii->pbus, PCI_GPIO_OUT,
+       sii = (struct si_info *)sih;
+       if (ai_get_ccrev(&sii->pub) < 6) {
+               pci_read_config_dword(sii->pcibus, PCI_GPIO_OUT,
                                      &val);
                if (val & PCI_CFG_GPIO_SCS)
                        return SCC_SS_PCI;
                return SCC_SS_XTAL;
-       } else if (sii->pub.ccrev < 10) {
-               cc = (struct chipcregs __iomem *)
-                       ai_setcoreidx(&sii->pub, sii->curidx);
-               return R_REG(&cc->slow_clk_ctl) & SCC_SS_MASK;
+       } else if (ai_get_ccrev(&sii->pub) < 10) {
+               return bcma_read32(cc, CHIPCREGOFFS(slow_clk_ctl)) &
+                      SCC_SS_MASK;
        } else                  /* Insta-clock */
                return SCC_SS_XTAL;
 }
@@ -1505,24 +776,24 @@ static uint ai_slowclk_src(struct si_info *sii)
 * return the ILP (slowclock) min or max frequency
 * precondition: we've established the chip has dynamic clk control
 */
-static uint ai_slowclk_freq(struct si_info *sii, bool max_freq,
-                           struct chipcregs __iomem *cc)
+static uint ai_slowclk_freq(struct si_pub *sih, bool max_freq,
+                           struct bcma_device *cc)
 {
        u32 slowclk;
        uint div;
 
-       slowclk = ai_slowclk_src(sii);
-       if (sii->pub.ccrev < 6) {
+       slowclk = ai_slowclk_src(sih, cc);
+       if (ai_get_ccrev(sih) < 6) {
                if (slowclk == SCC_SS_PCI)
                        return max_freq ? (PCIMAXFREQ / 64)
                                : (PCIMINFREQ / 64);
                else
                        return max_freq ? (XTALMAXFREQ / 32)
                                : (XTALMINFREQ / 32);
-       } else if (sii->pub.ccrev < 10) {
+       } else if (ai_get_ccrev(sih) < 10) {
                div = 4 *
-                   (((R_REG(&cc->slow_clk_ctl) & SCC_CD_MASK) >>
-                     SCC_CD_SHIFT) + 1);
+                   (((bcma_read32(cc, CHIPCREGOFFS(slow_clk_ctl)) &
+                     SCC_CD_MASK) >> SCC_CD_SHIFT) + 1);
                if (slowclk == SCC_SS_LPO)
                        return max_freq ? LPOMAXFREQ : LPOMINFREQ;
                else if (slowclk == SCC_SS_XTAL)
@@ -1533,15 +804,15 @@ static uint ai_slowclk_freq(struct si_info *sii, bool max_freq,
                                : (PCIMINFREQ / div);
        } else {
                /* Chipc rev 10 is InstaClock */
-               div = R_REG(&cc->system_clk_ctl) >> SYCC_CD_SHIFT;
-               div = 4 * (div + 1);
+               div = bcma_read32(cc, CHIPCREGOFFS(system_clk_ctl));
+               div = 4 * ((div >> SYCC_CD_SHIFT) + 1);
                return max_freq ? XTALMAXFREQ : (XTALMINFREQ / div);
        }
        return 0;
 }
 
 static void
-ai_clkctl_setdelay(struct si_info *sii, struct chipcregs __iomem *cc)
+ai_clkctl_setdelay(struct si_pub *sih, struct bcma_device *cc)
 {
        uint slowmaxfreq, pll_delay, slowclk;
        uint pll_on_delay, fref_sel_delay;
@@ -1554,55 +825,40 @@ ai_clkctl_setdelay(struct si_info *sii, struct chipcregs __iomem *cc)
         * powered down by dynamic clk control logic.
         */
 
-       slowclk = ai_slowclk_src(sii);
+       slowclk = ai_slowclk_src(sih, cc);
        if (slowclk != SCC_SS_XTAL)
                pll_delay += XTAL_ON_DELAY;
 
        /* Starting with 4318 it is ILP that is used for the delays */
        slowmaxfreq =
-           ai_slowclk_freq(sii, (sii->pub.ccrev >= 10) ? false : true, cc);
+           ai_slowclk_freq(sih,
+                           (ai_get_ccrev(sih) >= 10) ? false : true, cc);
 
        pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000;
        fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000;
 
-       W_REG(&cc->pll_on_delay, pll_on_delay);
-       W_REG(&cc->fref_sel_delay, fref_sel_delay);
+       bcma_write32(cc, CHIPCREGOFFS(pll_on_delay), pll_on_delay);
+       bcma_write32(cc, CHIPCREGOFFS(fref_sel_delay), fref_sel_delay);
 }
 
 /* initialize power control delay registers */
 void ai_clkctl_init(struct si_pub *sih)
 {
-       struct si_info *sii;
-       uint origidx = 0;
-       struct chipcregs __iomem *cc;
-       bool fast;
+       struct bcma_device *cc;
 
-       if (!(sih->cccaps & CC_CAP_PWR_CTL))
+       if (!(ai_get_cccaps(sih) & CC_CAP_PWR_CTL))
                return;
 
-       sii = (struct si_info *)sih;
-       fast = SI_FAST(sii);
-       if (!fast) {
-               origidx = sii->curidx;
-               cc = (struct chipcregs __iomem *)
-                       ai_setcore(sih, CC_CORE_ID, 0);
-               if (cc == NULL)
-                       return;
-       } else {
-               cc = (struct chipcregs __iomem *) CCREGS_FAST(sii);
-               if (cc == NULL)
-                       return;
-       }
+       cc = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0);
+       if (cc == NULL)
+               return;
 
        /* set all Instaclk chip ILP to 1 MHz */
-       if (sih->ccrev >= 10)
-               SET_REG(&cc->system_clk_ctl, SYCC_CD_MASK,
-                       (ILP_DIV_1MHZ << SYCC_CD_SHIFT));
+       if (ai_get_ccrev(sih) >= 10)
+               bcma_maskset32(cc, CHIPCREGOFFS(system_clk_ctl), SYCC_CD_MASK,
+                              (ILP_DIV_1MHZ << SYCC_CD_SHIFT));
 
-       ai_clkctl_setdelay(sii, cc);
-
-       if (!fast)
-               ai_setcoreidx(sih, origidx);
+       ai_clkctl_setdelay(sih, cc);
 }
 
 /*
@@ -1612,47 +868,25 @@ void ai_clkctl_init(struct si_pub *sih)
 u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih)
 {
        struct si_info *sii;
-       uint origidx = 0;
-       struct chipcregs __iomem *cc;
+       struct bcma_device *cc;
        uint slowminfreq;
        u16 fpdelay;
-       uint intr_val = 0;
-       bool fast;
 
        sii = (struct si_info *)sih;
-       if (sih->cccaps & CC_CAP_PMU) {
-               INTR_OFF(sii, intr_val);
+       if (ai_get_cccaps(sih) & CC_CAP_PMU) {
                fpdelay = si_pmu_fast_pwrup_delay(sih);
-               INTR_RESTORE(sii, intr_val);
                return fpdelay;
        }
 
-       if (!(sih->cccaps & CC_CAP_PWR_CTL))
+       if (!(ai_get_cccaps(sih) & CC_CAP_PWR_CTL))
                return 0;
 
-       fast = SI_FAST(sii);
        fpdelay = 0;
-       if (!fast) {
-               origidx = sii->curidx;
-               INTR_OFF(sii, intr_val);
-               cc = (struct chipcregs __iomem *)
-                       ai_setcore(sih, CC_CORE_ID, 0);
-               if (cc == NULL)
-                       goto done;
-       } else {
-               cc = (struct chipcregs __iomem *) CCREGS_FAST(sii);
-               if (cc == NULL)
-                       goto done;
-       }
-
-       slowminfreq = ai_slowclk_freq(sii, false, cc);
-       fpdelay = (((R_REG(&cc->pll_on_delay) + 2) * 1000000) +
-                  (slowminfreq - 1)) / slowminfreq;
-
- done:
-       if (!fast) {
-               ai_setcoreidx(sih, origidx);
-               INTR_RESTORE(sii, intr_val);
+       cc = ai_findcore(sih, CC_CORE_ID, 0);
+       if (cc) {
+               slowminfreq = ai_slowclk_freq(sih, false, cc);
+               fpdelay = (((bcma_read32(cc, CHIPCREGOFFS(pll_on_delay)) + 2)
+                           * 1000000) + (slowminfreq - 1)) / slowminfreq;
        }
        return fpdelay;
 }
@@ -1666,12 +900,12 @@ int ai_clkctl_xtal(struct si_pub *sih, uint what, bool on)
        sii = (struct si_info *)sih;
 
        /* pcie core doesn't have any mapping to control the xtal pu */
-       if (PCIE(sii))
+       if (PCIE(sih))
                return -1;
 
-       pci_read_config_dword(sii->pbus, PCI_GPIO_IN, &in);
-       pci_read_config_dword(sii->pbus, PCI_GPIO_OUT, &out);
-       pci_read_config_dword(sii->pbus, PCI_GPIO_OUTEN, &outen);
+       pci_read_config_dword(sii->pcibus, PCI_GPIO_IN, &in);
+       pci_read_config_dword(sii->pcibus, PCI_GPIO_OUT, &out);
+       pci_read_config_dword(sii->pcibus, PCI_GPIO_OUTEN, &outen);
 
        /*
         * Avoid glitching the clock if GPRS is already using it.
@@ -1692,9 +926,9 @@ int ai_clkctl_xtal(struct si_pub *sih, uint what, bool on)
                        out |= PCI_CFG_GPIO_XTAL;
                        if (what & PLL)
                                out |= PCI_CFG_GPIO_PLL;
-                       pci_write_config_dword(sii->pbus,
+                       pci_write_config_dword(sii->pcibus,
                                               PCI_GPIO_OUT, out);
-                       pci_write_config_dword(sii->pbus,
+                       pci_write_config_dword(sii->pcibus,
                                               PCI_GPIO_OUTEN, outen);
                        udelay(XTAL_ON_DELAY);
                }
@@ -1702,7 +936,7 @@ int ai_clkctl_xtal(struct si_pub *sih, uint what, bool on)
                /* turn pll on */
                if (what & PLL) {
                        out &= ~PCI_CFG_GPIO_PLL;
-                       pci_write_config_dword(sii->pbus,
+                       pci_write_config_dword(sii->pcibus,
                                               PCI_GPIO_OUT, out);
                        mdelay(2);
                }
@@ -1711,9 +945,9 @@ int ai_clkctl_xtal(struct si_pub *sih, uint what, bool on)
                        out &= ~PCI_CFG_GPIO_XTAL;
                if (what & PLL)
                        out |= PCI_CFG_GPIO_PLL;
-               pci_write_config_dword(sii->pbus,
+               pci_write_config_dword(sii->pcibus,
                                       PCI_GPIO_OUT, out);
-               pci_write_config_dword(sii->pbus,
+               pci_write_config_dword(sii->pcibus,
                                       PCI_GPIO_OUTEN, outen);
        }
 
@@ -1723,63 +957,52 @@ int ai_clkctl_xtal(struct si_pub *sih, uint what, bool on)
 /* clk control mechanism through chipcommon, no policy checking */
 static bool _ai_clkctl_cc(struct si_info *sii, uint mode)
 {
-       uint origidx = 0;
-       struct chipcregs __iomem *cc;
+       struct bcma_device *cc;
        u32 scc;
-       uint intr_val = 0;
-       bool fast = SI_FAST(sii);
 
        /* chipcommon cores prior to rev6 don't support dynamic clock control */
-       if (sii->pub.ccrev < 6)
+       if (ai_get_ccrev(&sii->pub) < 6)
                return false;
 
-       if (!fast) {
-               INTR_OFF(sii, intr_val);
-               origidx = sii->curidx;
-               cc = (struct chipcregs __iomem *)
-                                       ai_setcore(&sii->pub, CC_CORE_ID, 0);
-       } else {
-               cc = (struct chipcregs __iomem *) CCREGS_FAST(sii);
-               if (cc == NULL)
-                       goto done;
-       }
+       cc = ai_findcore(&sii->pub, BCMA_CORE_CHIPCOMMON, 0);
 
-       if (!(sii->pub.cccaps & CC_CAP_PWR_CTL) && (sii->pub.ccrev < 20))
-               goto done;
+       if (!(ai_get_cccaps(&sii->pub) & CC_CAP_PWR_CTL) &&
+           (ai_get_ccrev(&sii->pub) < 20))
+               return mode == CLK_FAST;
 
        switch (mode) {
        case CLK_FAST:          /* FORCEHT, fast (pll) clock */
-               if (sii->pub.ccrev < 10) {
+               if (ai_get_ccrev(&sii->pub) < 10) {
                        /*
                         * don't forget to force xtal back
                         * on before we clear SCC_DYN_XTAL..
                         */
                        ai_clkctl_xtal(&sii->pub, XTAL, ON);
-                       SET_REG(&cc->slow_clk_ctl,
-                               (SCC_XC | SCC_FS | SCC_IP), SCC_IP);
-               } else if (sii->pub.ccrev < 20) {
-                       OR_REG(&cc->system_clk_ctl, SYCC_HR);
+                       bcma_maskset32(cc, CHIPCREGOFFS(slow_clk_ctl),
+                                      (SCC_XC | SCC_FS | SCC_IP), SCC_IP);
+               } else if (ai_get_ccrev(&sii->pub) < 20) {
+                       bcma_set32(cc, CHIPCREGOFFS(system_clk_ctl), SYCC_HR);
                } else {
-                       OR_REG(&cc->clk_ctl_st, CCS_FORCEHT);
+                       bcma_set32(cc, CHIPCREGOFFS(clk_ctl_st), CCS_FORCEHT);
                }
 
                /* wait for the PLL */
-               if (sii->pub.cccaps & CC_CAP_PMU) {
+               if (ai_get_cccaps(&sii->pub) & CC_CAP_PMU) {
                        u32 htavail = CCS_HTAVAIL;
-                       SPINWAIT(((R_REG(&cc->clk_ctl_st) & htavail)
-                                 == 0), PMU_MAX_TRANSITION_DLY);
+                       SPINWAIT(((bcma_read32(cc, CHIPCREGOFFS(clk_ctl_st)) &
+                                  htavail) == 0), PMU_MAX_TRANSITION_DLY);
                } else {
                        udelay(PLL_DELAY);
                }
                break;
 
        case CLK_DYNAMIC:       /* enable dynamic clock control */
-               if (sii->pub.ccrev < 10) {
-                       scc = R_REG(&cc->slow_clk_ctl);
+               if (ai_get_ccrev(&sii->pub) < 10) {
+                       scc = bcma_read32(cc, CHIPCREGOFFS(slow_clk_ctl));
                        scc &= ~(SCC_FS | SCC_IP | SCC_XC);
                        if ((scc & SCC_SS_MASK) != SCC_SS_XTAL)
                                scc |= SCC_XC;
-                       W_REG(&cc->slow_clk_ctl, scc);
+                       bcma_write32(cc, CHIPCREGOFFS(slow_clk_ctl), scc);
 
                        /*
                         * for dynamic control, we have to
@@ -1787,11 +1010,11 @@ static bool _ai_clkctl_cc(struct si_info *sii, uint mode)
                         */
                        if (scc & SCC_XC)
                                ai_clkctl_xtal(&sii->pub, XTAL, OFF);
-               } else if (sii->pub.ccrev < 20) {
+               } else if (ai_get_ccrev(&sii->pub) < 20) {
                        /* Instaclock */
-                       AND_REG(&cc->system_clk_ctl, ~SYCC_HR);
+                       bcma_mask32(cc, CHIPCREGOFFS(system_clk_ctl), ~SYCC_HR);
                } else {
-                       AND_REG(&cc->clk_ctl_st, ~CCS_FORCEHT);
+                       bcma_mask32(cc, CHIPCREGOFFS(clk_ctl_st), ~CCS_FORCEHT);
                }
                break;
 
@@ -1799,11 +1022,6 @@ static bool _ai_clkctl_cc(struct si_info *sii, uint mode)
                break;
        }
 
- done:
-       if (!fast) {
-               ai_setcoreidx(&sii->pub, origidx);
-               INTR_RESTORE(sii, intr_val);
-       }
        return mode == CLK_FAST;
 }
 
@@ -1822,46 +1040,25 @@ bool ai_clkctl_cc(struct si_pub *sih, uint mode)
        sii = (struct si_info *)sih;
 
        /* chipcommon cores prior to rev6 don't support dynamic clock control */
-       if (sih->ccrev < 6)
+       if (ai_get_ccrev(sih) < 6)
                return false;
 
-       if (PCI_FORCEHT(sii))
+       if (PCI_FORCEHT(sih))
                return mode == CLK_FAST;
 
        return _ai_clkctl_cc(sii, mode);
 }
 
-/* Build device path */
-int ai_devpath(struct si_pub *sih, char *path, int size)
-{
-       int slen;
-
-       if (!path || size <= 0)
-               return -1;
-
-       slen = snprintf(path, (size_t) size, "pci/%u/%u/",
-               ((struct si_info *)sih)->pbus->bus->number,
-               PCI_SLOT(((struct pci_dev *)
-                               (((struct si_info *)(sih))->pbus))->devfn));
-
-       if (slen < 0 || slen >= size) {
-               path[0] = '\0';
-               return -1;
-       }
-
-       return 0;
-}
-
 void ai_pci_up(struct si_pub *sih)
 {
        struct si_info *sii;
 
        sii = (struct si_info *)sih;
 
-       if (PCI_FORCEHT(sii))
+       if (PCI_FORCEHT(sih))
                _ai_clkctl_cc(sii, CLK_FAST);
 
-       if (PCIE(sii))
+       if (PCIE(sih))
                pcicore_up(sii->pch, SI_PCIUP);
 
 }
@@ -1884,7 +1081,7 @@ void ai_pci_down(struct si_pub *sih)
        sii = (struct si_info *)sih;
 
        /* release FORCEHT since chip is going to "down" state */
-       if (PCI_FORCEHT(sii))
+       if (PCI_FORCEHT(sih))
                _ai_clkctl_cc(sii, CLK_DYNAMIC);
 
        pcicore_down(sii->pch, SI_PCIDOWN);
@@ -1897,42 +1094,23 @@ void ai_pci_down(struct si_pub *sih)
 void ai_pci_setup(struct si_pub *sih, uint coremask)
 {
        struct si_info *sii;
-       struct sbpciregs __iomem *regs = NULL;
-       u32 siflag = 0, w;
-       uint idx = 0;
+       u32 w;
 
        sii = (struct si_info *)sih;
 
-       if (PCI(sii)) {
-               /* get current core index */
-               idx = sii->curidx;
-
-               /* we interrupt on this backplane flag number */
-               siflag = ai_flag(sih);
-
-               /* switch over to pci core */
-               regs = ai_setcoreidx(sih, sii->pub.buscoreidx);
-       }
-
        /*
         * Enable sb->pci interrupts.  Assume
         * PCI rev 2.3 support was added in pci core rev 6 and things changed..
         */
-       if (PCIE(sii) || (PCI(sii) && ((sii->pub.buscorerev) >= 6))) {
+       if (PCIE(sih) || (PCI(sih) && (ai_get_buscorerev(sih) >= 6))) {
                /* pci config write to set this core bit in PCIIntMask */
-               pci_read_config_dword(sii->pbus, PCI_INT_MASK, &w);
+               pci_read_config_dword(sii->pcibus, PCI_INT_MASK, &w);
                w |= (coremask << PCI_SBIM_SHIFT);
-               pci_write_config_dword(sii->pbus, PCI_INT_MASK, w);
-       } else {
-               /* set sbintvec bit for our flag number */
-               ai_setint(sih, siflag);
+               pci_write_config_dword(sii->pcibus, PCI_INT_MASK, w);
        }
 
-       if (PCI(sii)) {
-               pcicore_pci_setup(sii->pch, regs);
-
-               /* switch back to previous core */
-               ai_setcoreidx(sih, idx);
+       if (PCI(sih)) {
+               pcicore_pci_setup(sii->pch);
        }
 }
 
@@ -1942,25 +1120,11 @@ void ai_pci_setup(struct si_pub *sih, uint coremask)
  */
 int ai_pci_fixcfg(struct si_pub *sih)
 {
-       uint origidx;
-       void __iomem *regs = NULL;
        struct si_info *sii = (struct si_info *)sih;
 
        /* Fixup PI in SROM shadow area to enable the correct PCI core access */
-       /* save the current index */
-       origidx = ai_coreidx(&sii->pub);
-
        /* check 'pi' is correct and fix it if not */
-       regs = ai_setcore(&sii->pub, sii->pub.buscoretype, 0);
-       if (sii->pub.buscoretype == PCIE_CORE_ID)
-               pcicore_fixcfg_pcie(sii->pch,
-                                   (struct sbpcieregs __iomem *)regs);
-       else if (sii->pub.buscoretype == PCI_CORE_ID)
-               pcicore_fixcfg_pci(sii->pch, (struct sbpciregs __iomem *)regs);
-
-       /* restore the original index */
-       ai_setcoreidx(&sii->pub, origidx);
-
+       pcicore_fixcfg(sii->pch);
        pcicore_hwup(sii->pch);
        return 0;
 }
@@ -1971,58 +1135,42 @@ u32 ai_gpiocontrol(struct si_pub *sih, u32 mask, u32 val, u8 priority)
        uint regoff;
 
        regoff = offsetof(struct chipcregs, gpiocontrol);
-       return ai_corereg(sih, SI_CC_IDX, regoff, mask, val);
+       return ai_cc_reg(sih, regoff, mask, val);
 }
 
 void ai_chipcontrl_epa4331(struct si_pub *sih, bool on)
 {
-       struct si_info *sii;
-       struct chipcregs __iomem *cc;
-       uint origidx;
+       struct bcma_device *cc;
        u32 val;
 
-       sii = (struct si_info *)sih;
-       origidx = ai_coreidx(sih);
-
-       cc = (struct chipcregs __iomem *) ai_setcore(sih, CC_CORE_ID, 0);
-
-       val = R_REG(&cc->chipcontrol);
+       cc = ai_findcore(sih, CC_CORE_ID, 0);
 
        if (on) {
-               if (sih->chippkg == 9 || sih->chippkg == 0xb)
+               if (ai_get_chippkg(sih) == 9 || ai_get_chippkg(sih) == 0xb)
                        /* Ext PA Controls for 4331 12x9 Package */
-                       W_REG(&cc->chipcontrol, val |
-                             CCTRL4331_EXTPA_EN |
-                             CCTRL4331_EXTPA_ON_GPIO2_5);
+                       bcma_set32(cc, CHIPCREGOFFS(chipcontrol),
+                                  CCTRL4331_EXTPA_EN |
+                                  CCTRL4331_EXTPA_ON_GPIO2_5);
                else
                        /* Ext PA Controls for 4331 12x12 Package */
-                       W_REG(&cc->chipcontrol,
-                             val | CCTRL4331_EXTPA_EN);
+                       bcma_set32(cc, CHIPCREGOFFS(chipcontrol),
+                                  CCTRL4331_EXTPA_EN);
        } else {
                val &= ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5);
-               W_REG(&cc->chipcontrol, val);
+               bcma_mask32(cc, CHIPCREGOFFS(chipcontrol),
+                           ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5));
        }
-
-       ai_setcoreidx(sih, origidx);
 }
 
 /* Enable BT-COEX & Ex-PA for 4313 */
 void ai_epa_4313war(struct si_pub *sih)
 {
-       struct si_info *sii;
-       struct chipcregs __iomem *cc;
-       uint origidx;
+       struct bcma_device *cc;
 
-       sii = (struct si_info *)sih;
-       origidx = ai_coreidx(sih);
-
-       cc = ai_setcore(sih, CC_CORE_ID, 0);
+       cc = ai_findcore(sih, CC_CORE_ID, 0);
 
        /* EPA Fix */
-       W_REG(&cc->gpiocontrol,
-             R_REG(&cc->gpiocontrol) | GPIO_CTRL_EPA_EN_MASK);
-
-       ai_setcoreidx(sih, origidx);
+       bcma_set32(cc, CHIPCREGOFFS(gpiocontrol), GPIO_CTRL_EPA_EN_MASK);
 }
 
 /* check if the device is removed */
@@ -2033,7 +1181,7 @@ bool ai_deviceremoved(struct si_pub *sih)
 
        sii = (struct si_info *)sih;
 
-       pci_read_config_dword(sii->pbus, PCI_VENDOR_ID, &w);
+       pci_read_config_dword(sii->pcibus, PCI_VENDOR_ID, &w);
        if ((w & 0xFFFF) != PCI_VENDOR_ID_BROADCOM)
                return true;
 
@@ -2042,26 +1190,23 @@ bool ai_deviceremoved(struct si_pub *sih)
 
 bool ai_is_sprom_available(struct si_pub *sih)
 {
-       if (sih->ccrev >= 31) {
-               struct si_info *sii;
-               uint origidx;
-               struct chipcregs __iomem *cc;
+       struct si_info *sii = (struct si_info *)sih;
+
+       if (ai_get_ccrev(sih) >= 31) {
+               struct bcma_device *cc;
                u32 sromctrl;
 
-               if ((sih->cccaps & CC_CAP_SROM) == 0)
+               if ((ai_get_cccaps(sih) & CC_CAP_SROM) == 0)
                        return false;
 
-               sii = (struct si_info *)sih;
-               origidx = sii->curidx;
-               cc = ai_setcoreidx(sih, SI_CC_IDX);
-               sromctrl = R_REG(&cc->sromcontrol);
-               ai_setcoreidx(sih, origidx);
+               cc = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0);
+               sromctrl = bcma_read32(cc, CHIPCREGOFFS(sromcontrol));
                return sromctrl & SRC_PRESENT;
        }
 
-       switch (sih->chip) {
+       switch (ai_get_chip_id(sih)) {
        case BCM4313_CHIP_ID:
-               return (sih->chipst & CST4313_SPROM_PRESENT) != 0;
+               return (sii->chipst & CST4313_SPROM_PRESENT) != 0;
        default:
                return true;
        }
@@ -2069,9 +1214,11 @@ bool ai_is_sprom_available(struct si_pub *sih)
 
 bool ai_is_otp_disabled(struct si_pub *sih)
 {
-       switch (sih->chip) {
+       struct si_info *sii = (struct si_info *)sih;
+
+       switch (ai_get_chip_id(sih)) {
        case BCM4313_CHIP_ID:
-               return (sih->chipst & CST4313_OTP_PRESENT) == 0;
+               return (sii->chipst & CST4313_OTP_PRESENT) == 0;
                /* These chips always have their OTP on */
        case BCM43224_CHIP_ID:
        case BCM43225_CHIP_ID:
@@ -2079,3 +1226,15 @@ bool ai_is_otp_disabled(struct si_pub *sih)
                return false;
        }
 }
+
+uint ai_get_buscoretype(struct si_pub *sih)
+{
+       struct si_info *sii = (struct si_info *)sih;
+       return sii->buscore->id.id;
+}
+
+uint ai_get_buscorerev(struct si_pub *sih)
+{
+       struct si_info *sii = (struct si_info *)sih;
+       return sii->buscore->id.rev;
+}
index b51d1e421e244ca0e92b2326d20c2c6b13fca5dd..f84c6f7816921caeb999d9b41dd07888811eb858 100644 (file)
@@ -17,6 +17,8 @@
 #ifndef        _BRCM_AIUTILS_H_
 #define        _BRCM_AIUTILS_H_
 
+#include <linux/bcma/bcma.h>
+
 #include "types.h"
 
 /*
  *   public (read-only) portion of aiutils handle returned by si_attach()
  */
 struct si_pub {
-       uint buscoretype;       /* PCI_CORE_ID, PCIE_CORE_ID, PCMCIA_CORE_ID */
-       uint buscorerev;        /* buscore rev */
-       uint buscoreidx;        /* buscore index */
        int ccrev;              /* chip common core rev */
        u32 cccaps;             /* chip common capabilities */
-       u32 cccaps_ext; /* chip common capabilities extension */
        int pmurev;             /* pmu core rev */
        u32 pmucaps;            /* pmu capabilities */
        uint boardtype;         /* board type */
        uint boardvendor;       /* board vendor */
-       uint boardflags;        /* board flags */
-       uint boardflags2;       /* board flags2 */
        uint chip;              /* chip number */
        uint chiprev;           /* chip revision */
        uint chippkg;           /* chip package option */
-       u32 chipst;             /* chip status */
-       bool issim;             /* chip is in simulation or emulation */
-       uint socirev;           /* SOC interconnect rev */
-       bool pci_pr32414;
-
 };
 
 struct pci_dev;
@@ -179,38 +170,13 @@ struct gpioh_item {
 /* misc si info needed by some of the routines */
 struct si_info {
        struct si_pub pub;      /* back plane public state (must be first) */
-       struct pci_dev *pbus;   /* handle to pci bus */
-       uint dev_coreid;        /* the core provides driver functions */
-       void *intr_arg;         /* interrupt callback function arg */
-       u32 (*intrsoff_fn) (void *intr_arg); /* turns chip interrupts off */
-       /* restore chip interrupts */
-       void (*intrsrestore_fn) (void *intr_arg, u32 arg);
-       /* check if interrupts are enabled */
-       bool (*intrsenabled_fn) (void *intr_arg);
-
+       struct bcma_bus *icbus; /* handle to soc interconnect bus */
+       struct pci_dev *pcibus; /* handle to pci bus */
        struct pcicore_info *pch; /* PCI/E core handle */
-
+       struct bcma_device *buscore;
        struct list_head var_list; /* list of srom variables */
 
-       void __iomem *curmap;                   /* current regs va */
-       void __iomem *regs[SI_MAXCORES];        /* other regs va */
-
-       uint curidx;            /* current core index */
-       uint numcores;          /* # discovered cores */
-       uint coreid[SI_MAXCORES]; /* id of each core */
-       u32 coresba[SI_MAXCORES]; /* backplane address of each core */
-       void *regs2[SI_MAXCORES]; /* 2nd virtual address per core (usbh20) */
-       u32 coresba2[SI_MAXCORES]; /* 2nd phys address per core (usbh20) */
-       u32 coresba_size[SI_MAXCORES]; /* backplane address space size */
-       u32 coresba2_size[SI_MAXCORES]; /* second address space size */
-
-       void *curwrap;          /* current wrapper va */
-       void *wrappers[SI_MAXCORES];    /* other cores wrapper va */
-       u32 wrapba[SI_MAXCORES];        /* address of controlling wrapper */
-
-       u32 cia[SI_MAXCORES];   /* erom cia entry for each core */
-       u32 cib[SI_MAXCORES];   /* erom cia entry for each core */
-       u32 oob_router; /* oob router registers for axi */
+       u32 chipst;             /* chip status */
 };
 
 /*
@@ -223,52 +189,15 @@ struct si_info {
 
 
 /* AMBA Interconnect exported externs */
-extern uint ai_flag(struct si_pub *sih);
-extern void ai_setint(struct si_pub *sih, int siflag);
-extern uint ai_coreidx(struct si_pub *sih);
-extern uint ai_corevendor(struct si_pub *sih);
-extern uint ai_corerev(struct si_pub *sih);
-extern bool ai_iscoreup(struct si_pub *sih);
-extern u32 ai_core_cflags(struct si_pub *sih, u32 mask, u32 val);
-extern void ai_core_cflags_wo(struct si_pub *sih, u32 mask, u32 val);
-extern u32 ai_core_sflags(struct si_pub *sih, u32 mask, u32 val);
-extern uint ai_corereg(struct si_pub *sih, uint coreidx, uint regoff, uint mask,
-                      uint val);
-extern void ai_core_reset(struct si_pub *sih, u32 bits, u32 resetbits);
-extern void ai_core_disable(struct si_pub *sih, u32 bits);
-extern int ai_numaddrspaces(struct si_pub *sih);
-extern u32 ai_addrspace(struct si_pub *sih, uint asidx);
-extern u32 ai_addrspacesize(struct si_pub *sih, uint asidx);
-extern void ai_write_wrap_reg(struct si_pub *sih, u32 offset, u32 val);
+extern struct bcma_device *ai_findcore(struct si_pub *sih,
+                                      u16 coreid, u16 coreunit);
+extern u32 ai_core_cflags(struct bcma_device *core, u32 mask, u32 val);
 
 /* === exported functions === */
-extern struct si_pub *ai_attach(void __iomem *regs, struct pci_dev *sdh);
+extern struct si_pub *ai_attach(struct bcma_bus *pbus);
 extern void ai_detach(struct si_pub *sih);
-extern uint ai_coreid(struct si_pub *sih);
-extern uint ai_corerev(struct si_pub *sih);
-extern uint ai_corereg(struct si_pub *sih, uint coreidx, uint regoff, uint mask,
-               uint val);
-extern void ai_write_wrapperreg(struct si_pub *sih, u32 offset, u32 val);
-extern u32 ai_core_cflags(struct si_pub *sih, u32 mask, u32 val);
-extern u32 ai_core_sflags(struct si_pub *sih, u32 mask, u32 val);
-extern bool ai_iscoreup(struct si_pub *sih);
-extern uint ai_findcoreidx(struct si_pub *sih, uint coreid, uint coreunit);
-extern void __iomem *ai_setcoreidx(struct si_pub *sih, uint coreidx);
-extern void __iomem *ai_setcore(struct si_pub *sih, uint coreid, uint coreunit);
-extern void __iomem *ai_switch_core(struct si_pub *sih, uint coreid,
-                                   uint *origidx, uint *intr_val);
-extern void ai_restore_core(struct si_pub *sih, uint coreid, uint intr_val);
-extern void ai_core_reset(struct si_pub *sih, u32 bits, u32 resetbits);
-extern void ai_core_disable(struct si_pub *sih, u32 bits);
-extern u32 ai_alp_clock(struct si_pub *sih);
-extern u32 ai_ilp_clock(struct si_pub *sih);
+extern uint ai_cc_reg(struct si_pub *sih, uint regoff, u32 mask, u32 val);
 extern void ai_pci_setup(struct si_pub *sih, uint coremask);
-extern void ai_setint(struct si_pub *sih, int siflag);
-extern bool ai_backplane64(struct si_pub *sih);
-extern void ai_register_intr_callback(struct si_pub *sih, void *intrsoff_fn,
-                                     void *intrsrestore_fn,
-                                     void *intrsenabled_fn, void *intr_arg);
-extern void ai_deregister_intr_callback(struct si_pub *sih);
 extern void ai_clkctl_init(struct si_pub *sih);
 extern u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih);
 extern bool ai_clkctl_cc(struct si_pub *sih, uint mode);
@@ -283,13 +212,6 @@ extern bool ai_is_otp_disabled(struct si_pub *sih);
 /* SPROM availability */
 extern bool ai_is_sprom_available(struct si_pub *sih);
 
-/*
- * Build device path. Path size must be >= SI_DEVPATH_BUFSZ.
- * The returned path is NULL terminated and has trailing '/'.
- * Return 0 on success, nonzero otherwise.
- */
-extern int ai_devpath(struct si_pub *sih, char *path, int size);
-
 extern void ai_pci_sleep(struct si_pub *sih);
 extern void ai_pci_down(struct si_pub *sih);
 extern void ai_pci_up(struct si_pub *sih);
@@ -299,4 +221,52 @@ extern void ai_chipcontrl_epa4331(struct si_pub *sih, bool on);
 /* Enable Ex-PA for 4313 */
 extern void ai_epa_4313war(struct si_pub *sih);
 
+extern uint ai_get_buscoretype(struct si_pub *sih);
+extern uint ai_get_buscorerev(struct si_pub *sih);
+
+static inline int ai_get_ccrev(struct si_pub *sih)
+{
+       return sih->ccrev;
+}
+
+static inline u32 ai_get_cccaps(struct si_pub *sih)
+{
+       return sih->cccaps;
+}
+
+static inline int ai_get_pmurev(struct si_pub *sih)
+{
+       return sih->pmurev;
+}
+
+static inline u32 ai_get_pmucaps(struct si_pub *sih)
+{
+       return sih->pmucaps;
+}
+
+static inline uint ai_get_boardtype(struct si_pub *sih)
+{
+       return sih->boardtype;
+}
+
+static inline uint ai_get_boardvendor(struct si_pub *sih)
+{
+       return sih->boardvendor;
+}
+
+static inline uint ai_get_chip_id(struct si_pub *sih)
+{
+       return sih->chip;
+}
+
+static inline uint ai_get_chiprev(struct si_pub *sih)
+{
+       return sih->chiprev;
+}
+
+static inline uint ai_get_chippkg(struct si_pub *sih)
+{
+       return sih->chippkg;
+}
+
 #endif                         /* _BRCM_AIUTILS_H_ */
index 43f7a724dda812f1a6c27ba21e3f0184e70b30ce..90911eec0cf55948fddecffb225eb1543412cc6a 100644 (file)
@@ -1118,14 +1118,17 @@ brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
                u8 status_delay = 0;
 
                /* wait till the next 8 bytes of txstatus is available */
-               while (((s1 = R_REG(&wlc->regs->frmtxstatus)) & TXS_V) == 0) {
+               s1 = bcma_read32(wlc->hw->d11core, D11REGOFFS(frmtxstatus));
+               while ((s1 & TXS_V) == 0) {
                        udelay(1);
                        status_delay++;
                        if (status_delay > 10)
                                return; /* error condition */
+                       s1 = bcma_read32(wlc->hw->d11core,
+                                        D11REGOFFS(frmtxstatus));
                }
 
-               s2 = R_REG(&wlc->regs->frmtxstatus2);
+               s2 = bcma_read32(wlc->hw->d11core, D11REGOFFS(frmtxstatus2));
        }
 
        if (scb) {
index ed51616abc85d04e5dba54a4359a0bf33fc5b3e4..1948cb2771e9a8687b8860ba6269456215d2f07e 100644 (file)
@@ -430,6 +430,9 @@ struct d11regs {
        u16 PAD[0x380]; /* 0x800 - 0xEFE */
 };
 
+/* d11 register field offset */
+#define D11REGOFFS(field)      offsetof(struct d11regs, field)
+
 #define        PIHR_BASE       0x0400  /* byte address of packed IHR region */
 
 /* biststatus */
index b55b1f6bb4ba68af83fe7d8ea570e4e0a2e37ad5..b4cf617276c933cbd4217b1bb9d6dbcaab815676 100644 (file)
 #include "dma.h"
 #include "soc.h"
 
+/*
+ * dma register field offset calculation
+ */
+#define DMA64REGOFFS(field)            offsetof(struct dma64regs, field)
+#define DMA64TXREGOFFS(di, field)      (di->d64txregbase + DMA64REGOFFS(field))
+#define DMA64RXREGOFFS(di, field)      (di->d64rxregbase + DMA64REGOFFS(field))
+
 /*
  * DMA hardware requires each descriptor ring to be 8kB aligned, and fit within
  * a contiguous 8kB physical address.
@@ -220,15 +227,16 @@ struct dma_info {
        uint *msg_level;        /* message level pointer */
        char name[MAXNAMEL];    /* callers name for diag msgs */
 
-       struct pci_dev *pbus;           /* bus handle */
+       struct bcma_device *core;
+       struct device *dmadev;
 
        bool dma64;     /* this dma engine is operating in 64-bit mode */
        bool addrext;   /* this dma engine supports DmaExtendedAddrChanges */
 
        /* 64-bit dma tx engine registers */
-       struct dma64regs __iomem *d64txregs;
+       uint d64txregbase;
        /* 64-bit dma rx engine registers */
-       struct dma64regs __iomem *d64rxregs;
+       uint d64rxregbase;
        /* pointer to dma64 tx descriptor ring */
        struct dma64desc *txd64;
        /* pointer to dma64 rx descriptor ring */
@@ -375,15 +383,16 @@ static uint _dma_ctrlflags(struct dma_info *di, uint mask, uint flags)
        if (dmactrlflags & DMA_CTRL_PEN) {
                u32 control;
 
-               control = R_REG(&di->d64txregs->control);
-               W_REG(&di->d64txregs->control,
+               control = bcma_read32(di->core, DMA64TXREGOFFS(di, control));
+               bcma_write32(di->core, DMA64TXREGOFFS(di, control),
                      control | D64_XC_PD);
-               if (R_REG(&di->d64txregs->control) & D64_XC_PD)
+               if (bcma_read32(di->core, DMA64TXREGOFFS(di, control)) &
+                   D64_XC_PD)
                        /* We *can* disable it so it is supported,
                         * restore control register
                         */
-                       W_REG(&di->d64txregs->control,
-                       control);
+                       bcma_write32(di->core, DMA64TXREGOFFS(di, control),
+                                    control);
                else
                        /* Not supported, don't allow it to be enabled */
                        dmactrlflags &= ~DMA_CTRL_PEN;
@@ -394,12 +403,12 @@ static uint _dma_ctrlflags(struct dma_info *di, uint mask, uint flags)
        return dmactrlflags;
 }
 
-static bool _dma64_addrext(struct dma64regs __iomem *dma64regs)
+static bool _dma64_addrext(struct dma_info *di, uint ctrl_offset)
 {
        u32 w;
-       OR_REG(&dma64regs->control, D64_XC_AE);
-       w = R_REG(&dma64regs->control);
-       AND_REG(&dma64regs->control, ~D64_XC_AE);
+       bcma_set32(di->core, ctrl_offset, D64_XC_AE);
+       w = bcma_read32(di->core, ctrl_offset);
+       bcma_mask32(di->core, ctrl_offset, ~D64_XC_AE);
        return (w & D64_XC_AE) == D64_XC_AE;
 }
 
@@ -412,13 +421,13 @@ static bool _dma_isaddrext(struct dma_info *di)
        /* DMA64 supports full 32- or 64-bit operation. AE is always valid */
 
        /* not all tx or rx channel are available */
-       if (di->d64txregs != NULL) {
-               if (!_dma64_addrext(di->d64txregs))
+       if (di->d64txregbase != 0) {
+               if (!_dma64_addrext(di, DMA64TXREGOFFS(di, control)))
                        DMA_ERROR("%s: DMA64 tx doesn't have AE set\n",
                                  di->name);
                return true;
-       } else if (di->d64rxregs != NULL) {
-               if (!_dma64_addrext(di->d64rxregs))
+       } else if (di->d64rxregbase != 0) {
+               if (!_dma64_addrext(di, DMA64RXREGOFFS(di, control)))
                        DMA_ERROR("%s: DMA64 rx doesn't have AE set\n",
                                  di->name);
                return true;
@@ -432,14 +441,14 @@ static bool _dma_descriptor_align(struct dma_info *di)
        u32 addrl;
 
        /* Check to see if the descriptors need to be aligned on 4K/8K or not */
-       if (di->d64txregs != NULL) {
-               W_REG(&di->d64txregs->addrlow, 0xff0);
-               addrl = R_REG(&di->d64txregs->addrlow);
+       if (di->d64txregbase != 0) {
+               bcma_write32(di->core, DMA64TXREGOFFS(di, addrlow), 0xff0);
+               addrl = bcma_read32(di->core, DMA64TXREGOFFS(di, addrlow));
                if (addrl != 0)
                        return false;
-       } else if (di->d64rxregs != NULL) {
-               W_REG(&di->d64rxregs->addrlow, 0xff0);
-               addrl = R_REG(&di->d64rxregs->addrlow);
+       } else if (di->d64rxregbase != 0) {
+               bcma_write32(di->core, DMA64RXREGOFFS(di, addrlow), 0xff0);
+               addrl = bcma_read32(di->core, DMA64RXREGOFFS(di, addrlow));
                if (addrl != 0)
                        return false;
        }
@@ -450,7 +459,7 @@ static bool _dma_descriptor_align(struct dma_info *di)
  * Descriptor table must start at the DMA hardware dictated alignment, so
  * allocated memory must be large enough to support this requirement.
  */
-static void *dma_alloc_consistent(struct pci_dev *pdev, uint size,
+static void *dma_alloc_consistent(struct dma_info *di, uint size,
                                  u16 align_bits, uint *alloced,
                                  dma_addr_t *pap)
 {
@@ -460,7 +469,7 @@ static void *dma_alloc_consistent(struct pci_dev *pdev, uint size,
                        size += align;
                *alloced = size;
        }
-       return pci_alloc_consistent(pdev, size, pap);
+       return dma_alloc_coherent(di->dmadev, size, pap, GFP_ATOMIC);
 }
 
 static
@@ -486,7 +495,7 @@ static void *dma_ringalloc(struct dma_info *di, u32 boundary, uint size,
        u32 desc_strtaddr;
        u32 alignbytes = 1 << *alignbits;
 
-       va = dma_alloc_consistent(di->pbus, size, *alignbits, alloced, descpa);
+       va = dma_alloc_consistent(di, size, *alignbits, alloced, descpa);
 
        if (NULL == va)
                return NULL;
@@ -495,8 +504,8 @@ static void *dma_ringalloc(struct dma_info *di, u32 boundary, uint size,
        if (((desc_strtaddr + size - 1) & boundary) != (desc_strtaddr
                                                        & boundary)) {
                *alignbits = dma_align_sizetobits(size);
-               pci_free_consistent(di->pbus, size, va, *descpa);
-               va = dma_alloc_consistent(di->pbus, size, *alignbits,
+               dma_free_coherent(di->dmadev, size, va, *descpa);
+               va = dma_alloc_consistent(di, size, *alignbits,
                        alloced, descpa);
        }
        return va;
@@ -556,12 +565,13 @@ static bool _dma_alloc(struct dma_info *di, uint direction)
 }
 
 struct dma_pub *dma_attach(char *name, struct si_pub *sih,
-                    void __iomem *dmaregstx, void __iomem *dmaregsrx,
-                    uint ntxd, uint nrxd,
-                    uint rxbufsize, int rxextheadroom,
-                    uint nrxpost, uint rxoffset, uint *msg_level)
+                          struct bcma_device *core,
+                          uint txregbase, uint rxregbase, uint ntxd, uint nrxd,
+                          uint rxbufsize, int rxextheadroom,
+                          uint nrxpost, uint rxoffset, uint *msg_level)
 {
        struct dma_info *di;
+       u8 rev = core->id.rev;
        uint size;
 
        /* allocate private info structure */
@@ -572,11 +582,13 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih,
        di->msg_level = msg_level ? msg_level : &dma_msg_level;
 
 
-       di->dma64 = ((ai_core_sflags(sih, 0, 0) & SISF_DMA64) == SISF_DMA64);
+       di->dma64 =
+               ((bcma_aread32(core, BCMA_IOST) & SISF_DMA64) == SISF_DMA64);
 
-       /* init dma reg pointer */
-       di->d64txregs = (struct dma64regs __iomem *) dmaregstx;
-       di->d64rxregs = (struct dma64regs __iomem *) dmaregsrx;
+       /* init dma reg info */
+       di->core = core;
+       di->d64txregbase = txregbase;
+       di->d64rxregbase = rxregbase;
 
        /*
         * Default flags (which can be changed by the driver calling
@@ -585,16 +597,17 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih,
         */
        _dma_ctrlflags(di, DMA_CTRL_ROC | DMA_CTRL_PEN, 0);
 
-       DMA_TRACE("%s: %s flags 0x%x ntxd %d nrxd %d rxbufsize %d rxextheadroom %d nrxpost %d rxoffset %d dmaregstx %p dmaregsrx %p\n",
-                 name, "DMA64",
+       DMA_TRACE("%s: %s flags 0x%x ntxd %d nrxd %d "
+                 "rxbufsize %d rxextheadroom %d nrxpost %d rxoffset %d "
+                 "txregbase %u rxregbase %u\n", name, "DMA64",
                  di->dma.dmactrlflags, ntxd, nrxd, rxbufsize,
-                 rxextheadroom, nrxpost, rxoffset, dmaregstx, dmaregsrx);
+                 rxextheadroom, nrxpost, rxoffset, txregbase, rxregbase);
 
        /* make a private copy of our callers name */
        strncpy(di->name, name, MAXNAMEL);
        di->name[MAXNAMEL - 1] = '\0';
 
-       di->pbus = ((struct si_info *)sih)->pbus;
+       di->dmadev = core->dma_dev;
 
        /* save tunables */
        di->ntxd = (u16) ntxd;
@@ -626,11 +639,11 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih,
        di->dataoffsetlow = di->ddoffsetlow;
        di->dataoffsethigh = di->ddoffsethigh;
        /* WAR64450 : DMACtl.Addr ext fields are not supported in SDIOD core. */
-       if ((ai_coreid(sih) == SDIOD_CORE_ID)
-           && ((ai_corerev(sih) > 0) && (ai_corerev(sih) <= 2)))
+       if ((core->id.id == SDIOD_CORE_ID)
+           && ((rev > 0) && (rev <= 2)))
                di->addrext = 0;
-       else if ((ai_coreid(sih) == I2S_CORE_ID) &&
-                ((ai_corerev(sih) == 0) || (ai_corerev(sih) == 1)))
+       else if ((core->id.id == I2S_CORE_ID) &&
+                ((rev == 0) || (rev == 1)))
                di->addrext = 0;
        else
                di->addrext = _dma_isaddrext(di);
@@ -749,13 +762,13 @@ void dma_detach(struct dma_pub *pub)
 
        /* free dma descriptor rings */
        if (di->txd64)
-               pci_free_consistent(di->pbus, di->txdalloc,
-                                   ((s8 *)di->txd64 - di->txdalign),
-                                   (di->txdpaorig));
+               dma_free_coherent(di->dmadev, di->txdalloc,
+                                 ((s8 *)di->txd64 - di->txdalign),
+                                 (di->txdpaorig));
        if (di->rxd64)
-               pci_free_consistent(di->pbus, di->rxdalloc,
-                                   ((s8 *)di->rxd64 - di->rxdalign),
-                                   (di->rxdpaorig));
+               dma_free_coherent(di->dmadev, di->rxdalloc,
+                                 ((s8 *)di->rxd64 - di->rxdalign),
+                                 (di->rxdpaorig));
 
        /* free packet pointer vectors */
        kfree(di->txp);
@@ -780,11 +793,15 @@ _dma_ddtable_init(struct dma_info *di, uint direction, dma_addr_t pa)
        if ((di->ddoffsetlow == 0)
            || !(pa & PCI32ADDR_HIGH)) {
                if (direction == DMA_TX) {
-                       W_REG(&di->d64txregs->addrlow, pa + di->ddoffsetlow);
-                       W_REG(&di->d64txregs->addrhigh, di->ddoffsethigh);
+                       bcma_write32(di->core, DMA64TXREGOFFS(di, addrlow),
+                                    pa + di->ddoffsetlow);
+                       bcma_write32(di->core, DMA64TXREGOFFS(di, addrhigh),
+                                    di->ddoffsethigh);
                } else {
-                       W_REG(&di->d64rxregs->addrlow, pa + di->ddoffsetlow);
-                       W_REG(&di->d64rxregs->addrhigh, di->ddoffsethigh);
+                       bcma_write32(di->core, DMA64RXREGOFFS(di, addrlow),
+                                    pa + di->ddoffsetlow);
+                       bcma_write32(di->core, DMA64RXREGOFFS(di, addrhigh),
+                                    di->ddoffsethigh);
                }
        } else {
                /* DMA64 32bits address extension */
@@ -795,15 +812,19 @@ _dma_ddtable_init(struct dma_info *di, uint direction, dma_addr_t pa)
                pa &= ~PCI32ADDR_HIGH;
 
                if (direction == DMA_TX) {
-                       W_REG(&di->d64txregs->addrlow, pa + di->ddoffsetlow);
-                       W_REG(&di->d64txregs->addrhigh, di->ddoffsethigh);
-                       SET_REG(&di->d64txregs->control,
-                               D64_XC_AE, (ae << D64_XC_AE_SHIFT));
+                       bcma_write32(di->core, DMA64TXREGOFFS(di, addrlow),
+                                    pa + di->ddoffsetlow);
+                       bcma_write32(di->core, DMA64TXREGOFFS(di, addrhigh),
+                                    di->ddoffsethigh);
+                       bcma_maskset32(di->core, DMA64TXREGOFFS(di, control),
+                                      D64_XC_AE, (ae << D64_XC_AE_SHIFT));
                } else {
-                       W_REG(&di->d64rxregs->addrlow, pa + di->ddoffsetlow);
-                       W_REG(&di->d64rxregs->addrhigh, di->ddoffsethigh);
-                       SET_REG(&di->d64rxregs->control,
-                               D64_RC_AE, (ae << D64_RC_AE_SHIFT));
+                       bcma_write32(di->core, DMA64RXREGOFFS(di, addrlow),
+                                    pa + di->ddoffsetlow);
+                       bcma_write32(di->core, DMA64RXREGOFFS(di, addrhigh),
+                                    di->ddoffsethigh);
+                       bcma_maskset32(di->core, DMA64RXREGOFFS(di, control),
+                                      D64_RC_AE, (ae << D64_RC_AE_SHIFT));
                }
        }
 }
@@ -815,9 +836,9 @@ static void _dma_rxenable(struct dma_info *di)
 
        DMA_TRACE("%s:\n", di->name);
 
-       control =
-           (R_REG(&di->d64rxregs->control) & D64_RC_AE) |
-           D64_RC_RE;
+       control = D64_RC_RE | (bcma_read32(di->core,
+                                          DMA64RXREGOFFS(di, control)) &
+                              D64_RC_AE);
 
        if ((dmactrlflags & DMA_CTRL_PEN) == 0)
                control |= D64_RC_PD;
@@ -825,7 +846,7 @@ static void _dma_rxenable(struct dma_info *di)
        if (dmactrlflags & DMA_CTRL_ROC)
                control |= D64_RC_OC;
 
-       W_REG(&di->d64rxregs->control,
+       bcma_write32(di->core, DMA64RXREGOFFS(di, control),
                ((di->rxoffset << D64_RC_RO_SHIFT) | control));
 }
 
@@ -868,7 +889,8 @@ static struct sk_buff *dma64_getnextrxp(struct dma_info *di, bool forceall)
                return NULL;
 
        curr =
-           B2I(((R_REG(&di->d64rxregs->status0) & D64_RS0_CD_MASK) -
+           B2I(((bcma_read32(di->core,
+                             DMA64RXREGOFFS(di, status0)) & D64_RS0_CD_MASK) -
                 di->rcvptrbase) & D64_RS0_CD_MASK, struct dma64desc);
 
        /* ignore curr if forceall */
@@ -882,7 +904,7 @@ static struct sk_buff *dma64_getnextrxp(struct dma_info *di, bool forceall)
        pa = le32_to_cpu(di->rxd64[i].addrlow) - di->dataoffsetlow;
 
        /* clear this packet from the descriptor ring */
-       pci_unmap_single(di->pbus, pa, di->rxbufsize, PCI_DMA_FROMDEVICE);
+       dma_unmap_single(di->dmadev, pa, di->rxbufsize, DMA_FROM_DEVICE);
 
        di->rxd64[i].addrlow = cpu_to_le32(0xdeadbeef);
        di->rxd64[i].addrhigh = cpu_to_le32(0xdeadbeef);
@@ -950,12 +972,12 @@ int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list)
                if (resid > 0) {
                        uint cur;
                        cur =
-                           B2I(((R_REG(&di->d64rxregs->status0) &
-                                 D64_RS0_CD_MASK) -
-                                di->rcvptrbase) & D64_RS0_CD_MASK,
-                               struct dma64desc);
+                           B2I(((bcma_read32(di->core,
+                                             DMA64RXREGOFFS(di, status0)) &
+                                 D64_RS0_CD_MASK) - di->rcvptrbase) &
+                               D64_RS0_CD_MASK, struct dma64desc);
                        DMA_ERROR("rxin %d rxout %d, hw_curr %d\n",
-                                 di->rxin, di->rxout, cur);
+                                  di->rxin, di->rxout, cur);
                }
 #endif                         /* BCMDBG */
 
@@ -983,8 +1005,10 @@ static bool dma64_rxidle(struct dma_info *di)
        if (di->nrxd == 0)
                return true;
 
-       return ((R_REG(&di->d64rxregs->status0) & D64_RS0_CD_MASK) ==
-               (R_REG(&di->d64rxregs->ptr) & D64_RS0_CD_MASK));
+       return ((bcma_read32(di->core,
+                            DMA64RXREGOFFS(di, status0)) & D64_RS0_CD_MASK) ==
+               (bcma_read32(di->core, DMA64RXREGOFFS(di, ptr)) &
+                D64_RS0_CD_MASK));
 }
 
 /*
@@ -1048,8 +1072,8 @@ bool dma_rxfill(struct dma_pub *pub)
                 */
                *(u32 *) (p->data) = 0;
 
-               pa = pci_map_single(di->pbus, p->data,
-                       di->rxbufsize, PCI_DMA_FROMDEVICE);
+               pa = dma_map_single(di->dmadev, p->data, di->rxbufsize,
+                                   DMA_FROM_DEVICE);
 
                /* save the free packet pointer */
                di->rxp[rxout] = p;
@@ -1067,7 +1091,7 @@ bool dma_rxfill(struct dma_pub *pub)
        di->rxout = rxout;
 
        /* update the chip lastdscr pointer */
-       W_REG(&di->d64rxregs->ptr,
+       bcma_write32(di->core, DMA64RXREGOFFS(di, ptr),
              di->rcvptrbase + I2B(rxout, struct dma64desc));
 
        return ring_empty;
@@ -1128,7 +1152,7 @@ void dma_txinit(struct dma_pub *pub)
 
        if ((di->dma.dmactrlflags & DMA_CTRL_PEN) == 0)
                control |= D64_XC_PD;
-       OR_REG(&di->d64txregs->control, control);
+       bcma_set32(di->core, DMA64TXREGOFFS(di, control), control);
 
        /* DMA engine with alignment requirement requires table to be inited
         * before enabling the engine
@@ -1146,7 +1170,7 @@ void dma_txsuspend(struct dma_pub *pub)
        if (di->ntxd == 0)
                return;
 
-       OR_REG(&di->d64txregs->control, D64_XC_SE);
+       bcma_set32(di->core, DMA64TXREGOFFS(di, control), D64_XC_SE);
 }
 
 void dma_txresume(struct dma_pub *pub)
@@ -1158,7 +1182,7 @@ void dma_txresume(struct dma_pub *pub)
        if (di->ntxd == 0)
                return;
 
-       AND_REG(&di->d64txregs->control, ~D64_XC_SE);
+       bcma_mask32(di->core, DMA64TXREGOFFS(di, control), ~D64_XC_SE);
 }
 
 bool dma_txsuspended(struct dma_pub *pub)
@@ -1166,8 +1190,9 @@ bool dma_txsuspended(struct dma_pub *pub)
        struct dma_info *di = (struct dma_info *)pub;
 
        return (di->ntxd == 0) ||
-           ((R_REG(&di->d64txregs->control) & D64_XC_SE) ==
-            D64_XC_SE);
+              ((bcma_read32(di->core,
+                            DMA64TXREGOFFS(di, control)) & D64_XC_SE) ==
+               D64_XC_SE);
 }
 
 void dma_txreclaim(struct dma_pub *pub, enum txd_range range)
@@ -1200,16 +1225,17 @@ bool dma_txreset(struct dma_pub *pub)
                return true;
 
        /* suspend tx DMA first */
-       W_REG(&di->d64txregs->control, D64_XC_SE);
+       bcma_write32(di->core, DMA64TXREGOFFS(di, control), D64_XC_SE);
        SPINWAIT(((status =
-                  (R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK))
-                 != D64_XS0_XS_DISABLED) && (status != D64_XS0_XS_IDLE)
-                && (status != D64_XS0_XS_STOPPED), 10000);
+                  (bcma_read32(di->core, DMA64TXREGOFFS(di, status0)) &
+                   D64_XS0_XS_MASK)) != D64_XS0_XS_DISABLED) &&
+                 (status != D64_XS0_XS_IDLE) && (status != D64_XS0_XS_STOPPED),
+                10000);
 
-       W_REG(&di->d64txregs->control, 0);
+       bcma_write32(di->core, DMA64TXREGOFFS(di, control), 0);
        SPINWAIT(((status =
-                  (R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK))
-                 != D64_XS0_XS_DISABLED), 10000);
+                  (bcma_read32(di->core, DMA64TXREGOFFS(di, status0)) &
+                   D64_XS0_XS_MASK)) != D64_XS0_XS_DISABLED), 10000);
 
        /* wait for the last transaction to complete */
        udelay(300);
@@ -1225,10 +1251,10 @@ bool dma_rxreset(struct dma_pub *pub)
        if (di->nrxd == 0)
                return true;
 
-       W_REG(&di->d64rxregs->control, 0);
+       bcma_write32(di->core, DMA64RXREGOFFS(di, control), 0);
        SPINWAIT(((status =
-                  (R_REG(&di->d64rxregs->status0) & D64_RS0_RS_MASK))
-                 != D64_RS0_RS_DISABLED), 10000);
+                  (bcma_read32(di->core, DMA64RXREGOFFS(di, status0)) &
+                   D64_RS0_RS_MASK)) != D64_RS0_RS_DISABLED), 10000);
 
        return status == D64_RS0_RS_DISABLED;
 }
@@ -1267,7 +1293,7 @@ int dma_txfast(struct dma_pub *pub, struct sk_buff *p, bool commit)
                goto outoftxd;
 
        /* get physical address of buffer start */
-       pa = pci_map_single(di->pbus, data, len, PCI_DMA_TODEVICE);
+       pa = dma_map_single(di->dmadev, data, len, DMA_TO_DEVICE);
 
        /* With a DMA segment list, Descriptor table is filled
         * using the segment list instead of looping over
@@ -1290,7 +1316,7 @@ int dma_txfast(struct dma_pub *pub, struct sk_buff *p, bool commit)
 
        /* kick the chip */
        if (commit)
-               W_REG(&di->d64txregs->ptr,
+               bcma_write32(di->core, DMA64TXREGOFFS(di, ptr),
                      di->xmtptrbase + I2B(txout, struct dma64desc));
 
        /* tx flow control */
@@ -1338,16 +1364,15 @@ struct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range)
        if (range == DMA_RANGE_ALL)
                end = di->txout;
        else {
-               struct dma64regs __iomem *dregs = di->d64txregs;
-
-               end = (u16) (B2I(((R_REG(&dregs->status0) &
-                                D64_XS0_CD_MASK) -
-                                di->xmtptrbase) & D64_XS0_CD_MASK,
-                                struct dma64desc));
+               end = (u16) (B2I(((bcma_read32(di->core,
+                                              DMA64TXREGOFFS(di, status0)) &
+                                  D64_XS0_CD_MASK) - di->xmtptrbase) &
+                                D64_XS0_CD_MASK, struct dma64desc));
 
                if (range == DMA_RANGE_TRANSFERED) {
                        active_desc =
-                           (u16) (R_REG(&dregs->status1) &
+                               (u16)(bcma_read32(di->core,
+                                                 DMA64TXREGOFFS(di, status1)) &
                                      D64_XS1_AD_MASK);
                        active_desc =
                            (active_desc - di->xmtptrbase) & D64_XS0_CD_MASK;
@@ -1376,7 +1401,7 @@ struct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range)
                txp = di->txp[i];
                di->txp[i] = NULL;
 
-               pci_unmap_single(di->pbus, pa, size, PCI_DMA_TODEVICE);
+               dma_unmap_single(di->dmadev, pa, size, DMA_TO_DEVICE);
        }
 
        di->txin = i;
index d317c7c12f9181738e64681dfb60ba5292e94fa0..cc269ee5c49995f89d5c5c9a9d0183693935f2f7 100644 (file)
@@ -75,10 +75,11 @@ struct dma_pub {
 };
 
 extern struct dma_pub *dma_attach(char *name, struct si_pub *sih,
-                           void __iomem *dmaregstx, void __iomem *dmaregsrx,
-                           uint ntxd, uint nrxd,
-                           uint rxbufsize, int rxextheadroom,
-                           uint nrxpost, uint rxoffset, uint *msg_level);
+                                 struct bcma_device *d11core,
+                                 uint txregbase, uint rxregbase,
+                                 uint ntxd, uint nrxd,
+                                 uint rxbufsize, int rxextheadroom,
+                                 uint nrxpost, uint rxoffset, uint *msg_level);
 
 void dma_rxinit(struct dma_pub *pub);
 int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list);
index 76376eb112fecb0cdbd488996daf15c940dafe18..77fdc45b43efe93dcec3dbc9ae3945e6f2b4b84f 100644 (file)
 #define __UNDEF_NO_VERSION__
 
 #include <linux/etherdevice.h>
-#include <linux/pci.h>
 #include <linux/sched.h>
 #include <linux/firmware.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
+#include <linux/bcma/bcma.h>
 #include <net/mac80211.h>
 #include <defs.h>
 #include "nicpci.h"
@@ -87,16 +87,14 @@ MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN driver.");
 MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN cards");
 MODULE_LICENSE("Dual BSD/GPL");
 
-/* recognized PCI IDs */
-static DEFINE_PCI_DEVICE_TABLE(brcms_pci_id_table) = {
-       { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, /* 43225 2G */
-       { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) }, /* 43224 DUAL */
-       { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, /* 4313 DUAL */
-       { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, /* 43224 Ven */
-       {0}
-};
 
-MODULE_DEVICE_TABLE(pci, brcms_pci_id_table);
+/* recognized BCMA Core IDs */
+static struct bcma_device_id brcms_coreid_table[] = {
+       BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 23, BCMA_ANY_CLASS),
+       BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 24, BCMA_ANY_CLASS),
+       BCMA_CORETABLE_END
+};
+MODULE_DEVICE_TABLE(bcma, brcms_coreid_table);
 
 #ifdef BCMDBG
 static int msglevel = 0xdeadbeef;
@@ -724,7 +722,7 @@ static const struct ieee80211_ops brcms_ops = {
 };
 
 /*
- * is called in brcms_pci_probe() context, therefore no locking required.
+ * is called in brcms_bcma_probe() context, therefore no locking required.
  */
 static int brcms_set_hint(struct brcms_info *wl, char *abbrev)
 {
@@ -864,25 +862,15 @@ static void brcms_free(struct brcms_info *wl)
 #endif
                kfree(t);
        }
-
-       /*
-        * unregister_netdev() calls get_stats() which may read chip
-        * registers so we cannot unmap the chip registers until
-        * after calling unregister_netdev() .
-        */
-       if (wl->regsva)
-               iounmap(wl->regsva);
-
-       wl->regsva = NULL;
 }
 
 /*
 * called from both kernel as from this kernel module (error flow on attach)
 * precondition: perimeter lock is not acquired.
 */
-static void brcms_remove(struct pci_dev *pdev)
+static void brcms_remove(struct bcma_device *pdev)
 {
-       struct ieee80211_hw *hw = pci_get_drvdata(pdev);
+       struct ieee80211_hw *hw = bcma_get_drvdata(pdev);
        struct brcms_info *wl = hw->priv;
 
        if (wl->wlc) {
@@ -890,11 +878,10 @@ static void brcms_remove(struct pci_dev *pdev)
                wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
                ieee80211_unregister_hw(hw);
        }
-       pci_disable_device(pdev);
 
        brcms_free(wl);
 
-       pci_set_drvdata(pdev, NULL);
+       bcma_set_drvdata(pdev, NULL);
        ieee80211_free_hw(hw);
 }
 
@@ -1002,11 +989,9 @@ static int ieee_hw_init(struct ieee80211_hw *hw)
  * it as static.
  *
  *
- * is called in brcms_pci_probe() context, therefore no locking required.
+ * is called in brcms_bcma_probe() context, therefore no locking required.
  */
-static struct brcms_info *brcms_attach(u16 vendor, u16 device,
-                                      resource_size_t regs,
-                                      struct pci_dev *btparam, uint irq)
+static struct brcms_info *brcms_attach(struct bcma_device *pdev)
 {
        struct brcms_info *wl = NULL;
        int unit, err;
@@ -1020,7 +1005,7 @@ static struct brcms_info *brcms_attach(u16 vendor, u16 device,
                return NULL;
 
        /* allocate private info */
-       hw = pci_get_drvdata(btparam);  /* btparam == pdev */
+       hw = bcma_get_drvdata(pdev);
        if (hw != NULL)
                wl = hw->priv;
        if (WARN_ON(hw == NULL) || WARN_ON(wl == NULL))
@@ -1032,26 +1017,20 @@ static struct brcms_info *brcms_attach(u16 vendor, u16 device,
        /* setup the bottom half handler */
        tasklet_init(&wl->tasklet, brcms_dpc, (unsigned long) wl);
 
-       wl->regsva = ioremap_nocache(regs, PCI_BAR0_WINSZ);
-       if (wl->regsva == NULL) {
-               wiphy_err(wl->wiphy, "wl%d: ioremap() failed\n", unit);
-               goto fail;
-       }
        spin_lock_init(&wl->lock);
        spin_lock_init(&wl->isr_lock);
 
        /* prepare ucode */
-       if (brcms_request_fw(wl, btparam) < 0) {
+       if (brcms_request_fw(wl, pdev->bus->host_pci) < 0) {
                wiphy_err(wl->wiphy, "%s: Failed to find firmware usually in "
                          "%s\n", KBUILD_MODNAME, "/lib/firmware/brcm");
                brcms_release_fw(wl);
-               brcms_remove(btparam);
+               brcms_remove(pdev);
                return NULL;
        }
 
        /* common load-time initialization */
-       wl->wlc = brcms_c_attach(wl, vendor, device, unit, false,
-                                wl->regsva, btparam, &err);
+       wl->wlc = brcms_c_attach((void *)wl, pdev, unit, false, &err);
        brcms_release_fw(wl);
        if (!wl->wlc) {
                wiphy_err(wl->wiphy, "%s: attach() failed with code %d\n",
@@ -1063,11 +1042,12 @@ static struct brcms_info *brcms_attach(u16 vendor, u16 device,
        wl->pub->ieee_hw = hw;
 
        /* register our interrupt handler */
-       if (request_irq(irq, brcms_isr, IRQF_SHARED, KBUILD_MODNAME, wl)) {
+       if (request_irq(pdev->bus->host_pci->irq, brcms_isr,
+                       IRQF_SHARED, KBUILD_MODNAME, wl)) {
                wiphy_err(wl->wiphy, "wl%d: request_irq() failed\n", unit);
                goto fail;
        }
-       wl->irq = irq;
+       wl->irq = pdev->bus->host_pci->irq;
 
        /* register module */
        brcms_c_module_register(wl->pub, "linux", wl, NULL);
@@ -1114,37 +1094,18 @@ fail:
  *
  * Perimeter lock is initialized in the course of this function.
  */
-static int __devinit
-brcms_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int __devinit brcms_bcma_probe(struct bcma_device *pdev)
 {
-       int rc;
        struct brcms_info *wl;
        struct ieee80211_hw *hw;
-       u32 val;
-
-       dev_info(&pdev->dev, "bus %d slot %d func %d irq %d\n",
-              pdev->bus->number, PCI_SLOT(pdev->devfn),
-              PCI_FUNC(pdev->devfn), pdev->irq);
 
-       if ((pdev->vendor != PCI_VENDOR_ID_BROADCOM) ||
-           ((pdev->device != 0x0576) &&
-            ((pdev->device & 0xff00) != 0x4300) &&
-            ((pdev->device & 0xff00) != 0x4700) &&
-            ((pdev->device < 43000) || (pdev->device > 43999))))
-               return -ENODEV;
+       dev_info(&pdev->dev, "mfg %x core %x rev %d class %d irq %d\n",
+                pdev->id.manuf, pdev->id.id, pdev->id.rev, pdev->id.class,
+                pdev->bus->host_pci->irq);
 
-       rc = pci_enable_device(pdev);
-       if (rc) {
-               pr_err("%s: Cannot enable device %d-%d_%d\n",
-                      __func__, pdev->bus->number, PCI_SLOT(pdev->devfn),
-                      PCI_FUNC(pdev->devfn));
+       if ((pdev->id.manuf != BCMA_MANUF_BCM) ||
+           (pdev->id.id != BCMA_CORE_80211))
                return -ENODEV;
-       }
-       pci_set_master(pdev);
-
-       pci_read_config_dword(pdev, 0x40, &val);
-       if ((val & 0x0000ff00) != 0)
-               pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
 
        hw = ieee80211_alloc_hw(sizeof(struct brcms_info), &brcms_ops);
        if (!hw) {
@@ -1154,14 +1115,11 @@ brcms_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        SET_IEEE80211_DEV(hw, &pdev->dev);
 
-       pci_set_drvdata(pdev, hw);
+       bcma_set_drvdata(pdev, hw);
 
        memset(hw->priv, 0, sizeof(*wl));
 
-       wl = brcms_attach(pdev->vendor, pdev->device,
-                         pci_resource_start(pdev, 0), pdev,
-                         pdev->irq);
-
+       wl = brcms_attach(pdev);
        if (!wl) {
                pr_err("%s: %s: brcms_attach failed!\n", KBUILD_MODNAME,
                       __func__);
@@ -1170,16 +1128,23 @@ brcms_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        return 0;
 }
 
-static int brcms_suspend(struct pci_dev *pdev, pm_message_t state)
+static int brcms_pci_suspend(struct pci_dev *pdev)
+{
+       pci_save_state(pdev);
+       pci_disable_device(pdev);
+       return pci_set_power_state(pdev, PCI_D3hot);
+}
+
+static int brcms_suspend(struct bcma_device *pdev, pm_message_t state)
 {
        struct brcms_info *wl;
        struct ieee80211_hw *hw;
 
-       hw = pci_get_drvdata(pdev);
+       hw = bcma_get_drvdata(pdev);
        wl = hw->priv;
        if (!wl) {
                wiphy_err(wl->wiphy,
-                         "brcms_suspend: pci_get_drvdata failed\n");
+                         "brcms_suspend: bcma_get_drvdata failed\n");
                return -ENODEV;
        }
 
@@ -1188,25 +1153,14 @@ static int brcms_suspend(struct pci_dev *pdev, pm_message_t state)
        wl->pub->hw_up = false;
        spin_unlock_bh(&wl->lock);
 
-       pci_save_state(pdev);
-       pci_disable_device(pdev);
-       return pci_set_power_state(pdev, PCI_D3hot);
+       /* temporarily do suspend ourselves */
+       return brcms_pci_suspend(pdev->bus->host_pci);
 }
 
-static int brcms_resume(struct pci_dev *pdev)
+static int brcms_pci_resume(struct pci_dev *pdev)
 {
-       struct brcms_info *wl;
-       struct ieee80211_hw *hw;
        int err = 0;
-       u32 val;
-
-       hw = pci_get_drvdata(pdev);
-       wl = hw->priv;
-       if (!wl) {
-               wiphy_err(wl->wiphy,
-                         "wl: brcms_resume: pci_get_drvdata failed\n");
-               return -ENODEV;
-       }
+       uint val;
 
        err = pci_set_power_state(pdev, PCI_D0);
        if (err)
@@ -1224,24 +1178,28 @@ static int brcms_resume(struct pci_dev *pdev)
        if ((val & 0x0000ff00) != 0)
                pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
 
+       return 0;
+}
+
+static int brcms_resume(struct bcma_device *pdev)
+{
        /*
-       *  done. driver will be put in up state
-       *  in brcms_ops_add_interface() call.
+       *  just do pci resume for now until bcma supports it.
        */
-       return err;
+       return brcms_pci_resume(pdev->bus->host_pci);
 }
 
-static struct pci_driver brcms_pci_driver = {
+static struct bcma_driver brcms_bcma_driver = {
        .name     = KBUILD_MODNAME,
-       .probe    = brcms_pci_probe,
+       .probe    = brcms_bcma_probe,
        .suspend  = brcms_suspend,
        .resume   = brcms_resume,
        .remove   = __devexit_p(brcms_remove),
-       .id_table = brcms_pci_id_table,
+       .id_table = brcms_coreid_table,
 };
 
 /**
- * This is the main entry point for the WL driver.
+ * This is the main entry point for the brcmsmac driver.
  *
  * This function determines if a device pointed to by pdev is a WL device,
  * and if so, performs a brcms_attach() on it.
@@ -1256,26 +1214,24 @@ static int __init brcms_module_init(void)
                brcm_msg_level = msglevel;
 #endif                         /* BCMDBG */
 
-       error = pci_register_driver(&brcms_pci_driver);
+       error = bcma_driver_register(&brcms_bcma_driver);
+       printk(KERN_ERR "%s: register returned %d\n", __func__, error);
        if (!error)
                return 0;
 
-
-
        return error;
 }
 
 /**
- * This function unloads the WL driver from the system.
+ * This function unloads the brcmsmac driver from the system.
  *
- * This function unconditionally unloads the WL driver module from the
+ * This function unconditionally unloads the brcmsmac driver module from the
  * system.
  *
  */
 static void __exit brcms_module_exit(void)
 {
-       pci_unregister_driver(&brcms_pci_driver);
-
+       bcma_driver_unregister(&brcms_bcma_driver);
 }
 
 module_init(brcms_module_init);
@@ -1562,7 +1518,7 @@ fail:
 }
 
 /*
- * Precondition: Since this function is called in brcms_pci_probe() context,
+ * Precondition: Since this function is called in brcms_bcma_probe() context,
  * no locking is required.
  */
 int brcms_ucode_init_uint(struct brcms_info *wl, size_t *n_bytes, u32 idx)
@@ -1602,7 +1558,7 @@ void brcms_ucode_free_buf(void *p)
 /*
  * checks validity of all firmware images loaded from user space
  *
- * Precondition: Since this function is called in brcms_pci_probe() context,
+ * Precondition: Since this function is called in brcms_bcma_probe() context,
  * no locking is required.
  */
 int brcms_check_firmwares(struct brcms_info *wl)
index 6242f188b717d4e6c7a1cf3d7f30043a00fc1c29..8f60419c37bf1e0d5d0c15062c8a1103b8248b61 100644 (file)
@@ -68,8 +68,6 @@ struct brcms_info {
        spinlock_t lock;        /* per-device perimeter lock */
        spinlock_t isr_lock;    /* per-device ISR synchronization lock */
 
-       /* regsva for unmap in brcms_free() */
-       void __iomem *regsva;   /* opaque chip registers virtual address */
 
        /* timer related fields */
        atomic_t callbacks;     /* # outstanding callback functions */
index 87f8f5d3d91fff1e416b7828e088bd340fe8a403..f7ed34034f88cf12ed53694edd6621e14cf26a44 100644 (file)
@@ -388,10 +388,13 @@ static u16 get_sifs(struct brcms_band *band)
  */
 static bool brcms_deviceremoved(struct brcms_c_info *wlc)
 {
+       u32 macctrl;
+
        if (!wlc->hw->clk)
                return ai_deviceremoved(wlc->hw->sih);
-       return (R_REG(&wlc->hw->regs->maccontrol) &
-               (MCTL_PSM_JMP_0 | MCTL_IHR_EN)) != MCTL_IHR_EN;
+       macctrl = bcma_read32(wlc->hw->d11core,
+                             D11REGOFFS(maccontrol));
+       return (macctrl & (MCTL_PSM_JMP_0 | MCTL_IHR_EN)) != MCTL_IHR_EN;
 }
 
 /* sum the individual fifo tx pending packet counts */
@@ -582,17 +585,15 @@ brcms_c_attach_malloc(uint unit, uint *err, uint devid)
 static void brcms_b_update_slot_timing(struct brcms_hardware *wlc_hw,
                                        bool shortslot)
 {
-       struct d11regs __iomem *regs;
-
-       regs = wlc_hw->regs;
+       struct bcma_device *core = wlc_hw->d11core;
 
        if (shortslot) {
                /* 11g short slot: 11a timing */
-               W_REG(&regs->ifs_slot, 0x0207); /* APHY_SLOT_TIME */
+               bcma_write16(core, D11REGOFFS(ifs_slot), 0x0207);
                brcms_b_write_shm(wlc_hw, M_DOT11_SLOT, APHY_SLOT_TIME);
        } else {
                /* 11g long slot: 11b timing */
-               W_REG(&regs->ifs_slot, 0x0212); /* BPHY_SLOT_TIME */
+               bcma_write16(core, D11REGOFFS(ifs_slot), 0x0212);
                brcms_b_write_shm(wlc_hw, M_DOT11_SLOT, BPHY_SLOT_TIME);
        }
 }
@@ -672,24 +673,22 @@ static uint brcms_c_calc_frame_time(struct brcms_c_info *wlc, u32 ratespec,
 static void brcms_c_write_inits(struct brcms_hardware *wlc_hw,
                                const struct d11init *inits)
 {
+       struct bcma_device *core = wlc_hw->d11core;
        int i;
-       u8 __iomem *base;
-       u8 __iomem *addr;
+       uint offset;
        u16 size;
        u32 value;
 
        BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
 
-       base = (u8 __iomem *)wlc_hw->regs;
-
        for (i = 0; inits[i].addr != cpu_to_le16(0xffff); i++) {
                size = le16_to_cpu(inits[i].size);
-               addr = base + le16_to_cpu(inits[i].addr);
+               offset = le16_to_cpu(inits[i].addr);
                value = le32_to_cpu(inits[i].value);
                if (size == 2)
-                       W_REG((u16 __iomem *)addr, value);
+                       bcma_write16(core, offset, value);
                else if (size == 4)
-                       W_REG((u32 __iomem *)addr, value);
+                       bcma_write32(core, offset, value);
                else
                        break;
        }
@@ -739,6 +738,14 @@ static void brcms_c_ucode_bsinit(struct brcms_hardware *wlc_hw)
        }
 }
 
+static void brcms_b_core_ioctl(struct brcms_hardware *wlc_hw, u32 m, u32 v)
+{
+       struct bcma_device *core = wlc_hw->d11core;
+       u32 ioctl = bcma_aread32(core, BCMA_IOCTL) & ~m;
+
+       bcma_awrite32(core, BCMA_IOCTL, ioctl | v);
+}
+
 static void brcms_b_core_phy_clk(struct brcms_hardware *wlc_hw, bool clk)
 {
        BCMMSG(wlc_hw->wlc->wiphy, "wl%d: clk %d\n", wlc_hw->unit, clk);
@@ -747,17 +754,17 @@ static void brcms_b_core_phy_clk(struct brcms_hardware *wlc_hw, bool clk)
 
        if (OFF == clk) {       /* clear gmode bit, put phy into reset */
 
-               ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC | SICF_GMODE),
-                              (SICF_PRST | SICF_FGC));
+               brcms_b_core_ioctl(wlc_hw, (SICF_PRST | SICF_FGC | SICF_GMODE),
+                                  (SICF_PRST | SICF_FGC));
                udelay(1);
-               ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC), SICF_PRST);
+               brcms_b_core_ioctl(wlc_hw, (SICF_PRST | SICF_FGC), SICF_PRST);
                udelay(1);
 
        } else {                /* take phy out of reset */
 
-               ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC), SICF_FGC);
+               brcms_b_core_ioctl(wlc_hw, (SICF_PRST | SICF_FGC), SICF_FGC);
                udelay(1);
-               ai_core_cflags(wlc_hw->sih, (SICF_FGC), 0);
+               brcms_b_core_ioctl(wlc_hw, SICF_FGC, 0);
                udelay(1);
 
        }
@@ -778,9 +785,14 @@ static void brcms_c_setxband(struct brcms_hardware *wlc_hw, uint bandunit)
        wlc_hw->wlc->band = wlc_hw->wlc->bandstate[bandunit];
 
        /* set gmode core flag */
-       if (wlc_hw->sbclk && !wlc_hw->noreset)
-               ai_core_cflags(wlc_hw->sih, SICF_GMODE,
-                              ((bandunit == 0) ? SICF_GMODE : 0));
+       if (wlc_hw->sbclk && !wlc_hw->noreset) {
+               u32 gmode = 0;
+
+               if (bandunit == 0)
+                       gmode = SICF_GMODE;
+
+               brcms_b_core_ioctl(wlc_hw, SICF_GMODE, gmode);
+       }
 }
 
 /* switch to new band but leave it inactive */
@@ -788,10 +800,12 @@ static u32 brcms_c_setband_inact(struct brcms_c_info *wlc, uint bandunit)
 {
        struct brcms_hardware *wlc_hw = wlc->hw;
        u32 macintmask;
+       u32 macctrl;
 
        BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
-
-       WARN_ON((R_REG(&wlc_hw->regs->maccontrol) & MCTL_EN_MAC) != 0);
+       macctrl = bcma_read32(wlc_hw->d11core,
+                             D11REGOFFS(maccontrol));
+       WARN_ON((macctrl & MCTL_EN_MAC) != 0);
 
        /* disable interrupts */
        macintmask = brcms_intrsoff(wlc->wl);
@@ -982,7 +996,7 @@ brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal)
 {
        bool morepending = false;
        struct brcms_c_info *wlc = wlc_hw->wlc;
-       struct d11regs __iomem *regs;
+       struct bcma_device *core;
        struct tx_status txstatus, *txs;
        u32 s1, s2;
        uint n = 0;
@@ -995,18 +1009,18 @@ brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal)
        BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
 
        txs = &txstatus;
-       regs = wlc_hw->regs;
+       core = wlc_hw->d11core;
        *fatal = false;
+       s1 = bcma_read32(core, D11REGOFFS(frmtxstatus));
        while (!(*fatal)
-              && (s1 = R_REG(&regs->frmtxstatus)) & TXS_V) {
+              && (s1 & TXS_V)) {
 
                if (s1 == 0xffffffff) {
                        wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n",
                                wlc_hw->unit, __func__);
                        return morepending;
                }
-
-               s2 = R_REG(&regs->frmtxstatus2);
+               s2 = bcma_read32(core, D11REGOFFS(frmtxstatus2));
 
                txs->status = s1 & TXS_STATUS_MASK;
                txs->frameid = (s1 & TXS_FID_MASK) >> TXS_FID_SHIFT;
@@ -1019,6 +1033,7 @@ brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal)
                /* !give others some time to run! */
                if (++n >= max_tx_num)
                        break;
+               s1 = bcma_read32(core, D11REGOFFS(frmtxstatus));
        }
 
        if (*fatal)
@@ -1063,12 +1078,12 @@ brcms_c_mhfdef(struct brcms_c_info *wlc, u16 *mhfs, u16 mhf2_init)
        }
 }
 
-static struct dma64regs __iomem *
-dmareg(struct brcms_hardware *hw, uint direction, uint fifonum)
+static uint
+dmareg(uint direction, uint fifonum)
 {
        if (direction == DMA_TX)
-               return &(hw->regs->fifo64regs[fifonum].dmaxmt);
-       return &(hw->regs->fifo64regs[fifonum].dmarcv);
+               return offsetof(struct d11regs, fifo64regs[fifonum].dmaxmt);
+       return offsetof(struct d11regs, fifo64regs[fifonum].dmarcv);
 }
 
 static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme)
@@ -1094,9 +1109,9 @@ static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme)
                 * TX: TX_AC_BK_FIFO (TX AC Background data packets)
                 * RX: RX_FIFO (RX data packets)
                 */
-               wlc_hw->di[0] = dma_attach(name, wlc_hw->sih,
-                                          (wme ? dmareg(wlc_hw, DMA_TX, 0) :
-                                           NULL), dmareg(wlc_hw, DMA_RX, 0),
+               wlc_hw->di[0] = dma_attach(name, wlc_hw->sih, wlc_hw->d11core,
+                                          (wme ? dmareg(DMA_TX, 0) : 0),
+                                          dmareg(DMA_RX, 0),
                                           (wme ? NTXD : 0), NRXD,
                                           RXBUFSZ, -1, NRXBUFPOST,
                                           BRCMS_HWRXOFF, &brcm_msg_level);
@@ -1108,8 +1123,8 @@ static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme)
                 *   (legacy) TX_DATA_FIFO (TX data packets)
                 * RX: UNUSED
                 */
-               wlc_hw->di[1] = dma_attach(name, wlc_hw->sih,
-                                          dmareg(wlc_hw, DMA_TX, 1), NULL,
+               wlc_hw->di[1] = dma_attach(name, wlc_hw->sih, wlc_hw->d11core,
+                                          dmareg(DMA_TX, 1), 0,
                                           NTXD, 0, 0, -1, 0, 0,
                                           &brcm_msg_level);
                dma_attach_err |= (NULL == wlc_hw->di[1]);
@@ -1119,8 +1134,8 @@ static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme)
                 * TX: TX_AC_VI_FIFO (TX AC Video data packets)
                 * RX: UNUSED
                 */
-               wlc_hw->di[2] = dma_attach(name, wlc_hw->sih,
-                                          dmareg(wlc_hw, DMA_TX, 2), NULL,
+               wlc_hw->di[2] = dma_attach(name, wlc_hw->sih, wlc_hw->d11core,
+                                          dmareg(DMA_TX, 2), 0,
                                           NTXD, 0, 0, -1, 0, 0,
                                           &brcm_msg_level);
                dma_attach_err |= (NULL == wlc_hw->di[2]);
@@ -1129,9 +1144,9 @@ static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme)
                 * TX: TX_AC_VO_FIFO (TX AC Voice data packets)
                 *   (legacy) TX_CTL_FIFO (TX control & mgmt packets)
                 */
-               wlc_hw->di[3] = dma_attach(name, wlc_hw->sih,
-                                          dmareg(wlc_hw, DMA_TX, 3),
-                                          NULL, NTXD, 0, 0, -1,
+               wlc_hw->di[3] = dma_attach(name, wlc_hw->sih, wlc_hw->d11core,
+                                          dmareg(DMA_TX, 3),
+                                          0, NTXD, 0, 0, -1,
                                           0, 0, &brcm_msg_level);
                dma_attach_err |= (NULL == wlc_hw->di[3]);
 /* Cleaner to leave this as if with AP defined */
@@ -1205,7 +1220,7 @@ static void brcms_b_wait_for_wake(struct brcms_hardware *wlc_hw)
 /* control chip clock to save power, enable dynamic clock or force fast clock */
 static void brcms_b_clkctl_clk(struct brcms_hardware *wlc_hw, uint mode)
 {
-       if (wlc_hw->sih->cccaps & CC_CAP_PMU) {
+       if (ai_get_cccaps(wlc_hw->sih) & CC_CAP_PMU) {
                /* new chips with PMU, CCS_FORCEHT will distribute the HT clock
                 * on backplane, but mac core will still run on ALP(not HT) when
                 * it enters powersave mode, which means the FCA bit may not be
@@ -1214,29 +1229,33 @@ static void brcms_b_clkctl_clk(struct brcms_hardware *wlc_hw, uint mode)
 
                if (wlc_hw->clk) {
                        if (mode == CLK_FAST) {
-                               OR_REG(&wlc_hw->regs->clk_ctl_st,
-                                      CCS_FORCEHT);
+                               bcma_set32(wlc_hw->d11core,
+                                          D11REGOFFS(clk_ctl_st),
+                                          CCS_FORCEHT);
 
                                udelay(64);
 
-                               SPINWAIT(((R_REG
-                                          (&wlc_hw->regs->
-                                           clk_ctl_st) & CCS_HTAVAIL) == 0),
-                                        PMU_MAX_TRANSITION_DLY);
-                               WARN_ON(!(R_REG
-                                         (&wlc_hw->regs->
-                                          clk_ctl_st) & CCS_HTAVAIL));
+                               SPINWAIT(
+                                   ((bcma_read32(wlc_hw->d11core,
+                                     D11REGOFFS(clk_ctl_st)) &
+                                     CCS_HTAVAIL) == 0),
+                                     PMU_MAX_TRANSITION_DLY);
+                               WARN_ON(!(bcma_read32(wlc_hw->d11core,
+                                       D11REGOFFS(clk_ctl_st)) &
+                                       CCS_HTAVAIL));
                        } else {
-                               if ((wlc_hw->sih->pmurev == 0) &&
-                                   (R_REG
-                                    (&wlc_hw->regs->
-                                     clk_ctl_st) & (CCS_FORCEHT | CCS_HTAREQ)))
-                                       SPINWAIT(((R_REG
-                                                  (&wlc_hw->regs->
-                                                   clk_ctl_st) & CCS_HTAVAIL)
-                                                 == 0),
-                                                PMU_MAX_TRANSITION_DLY);
-                               AND_REG(&wlc_hw->regs->clk_ctl_st,
+                               if ((ai_get_pmurev(wlc_hw->sih) == 0) &&
+                                   (bcma_read32(wlc_hw->d11core,
+                                       D11REGOFFS(clk_ctl_st)) &
+                                       (CCS_FORCEHT | CCS_HTAREQ)))
+                                       SPINWAIT(
+                                           ((bcma_read32(wlc_hw->d11core,
+                                             offsetof(struct d11regs,
+                                                      clk_ctl_st)) &
+                                             CCS_HTAVAIL) == 0),
+                                             PMU_MAX_TRANSITION_DLY);
+                               bcma_mask32(wlc_hw->d11core,
+                                       D11REGOFFS(clk_ctl_st),
                                        ~CCS_FORCEHT);
                        }
                }
@@ -1251,7 +1270,7 @@ static void brcms_b_clkctl_clk(struct brcms_hardware *wlc_hw, uint mode)
 
                /* check fast clock is available (if core is not in reset) */
                if (wlc_hw->forcefastclk && wlc_hw->clk)
-                       WARN_ON(!(ai_core_sflags(wlc_hw->sih, 0, 0) &
+                       WARN_ON(!(bcma_aread32(wlc_hw->d11core, BCMA_IOST) &
                                  SISF_FCLKA));
 
                /*
@@ -1368,7 +1387,8 @@ static void brcms_c_mctrl_write(struct brcms_hardware *wlc_hw)
                maccontrol |= MCTL_INFRA;
        }
 
-       W_REG(&wlc_hw->regs->maccontrol, maccontrol);
+       bcma_write32(wlc_hw->d11core, D11REGOFFS(maccontrol),
+                    maccontrol);
 }
 
 /* set or clear maccontrol bits */
@@ -1462,7 +1482,7 @@ static void
 brcms_b_set_addrmatch(struct brcms_hardware *wlc_hw, int match_reg_offset,
                       const u8 *addr)
 {
-       struct d11regs __iomem *regs;
+       struct bcma_device *core = wlc_hw->d11core;
        u16 mac_l;
        u16 mac_m;
        u16 mac_h;
@@ -1470,38 +1490,36 @@ brcms_b_set_addrmatch(struct brcms_hardware *wlc_hw, int match_reg_offset,
        BCMMSG(wlc_hw->wlc->wiphy, "wl%d: brcms_b_set_addrmatch\n",
                 wlc_hw->unit);
 
-       regs = wlc_hw->regs;
        mac_l = addr[0] | (addr[1] << 8);
        mac_m = addr[2] | (addr[3] << 8);
        mac_h = addr[4] | (addr[5] << 8);
 
        /* enter the MAC addr into the RXE match registers */
-       W_REG(&regs->rcm_ctl, RCM_INC_DATA | match_reg_offset);
-       W_REG(&regs->rcm_mat_data, mac_l);
-       W_REG(&regs->rcm_mat_data, mac_m);
-       W_REG(&regs->rcm_mat_data, mac_h);
-
+       bcma_write16(core, D11REGOFFS(rcm_ctl),
+                    RCM_INC_DATA | match_reg_offset);
+       bcma_write16(core, D11REGOFFS(rcm_mat_data), mac_l);
+       bcma_write16(core, D11REGOFFS(rcm_mat_data), mac_m);
+       bcma_write16(core, D11REGOFFS(rcm_mat_data), mac_h);
 }
 
 void
 brcms_b_write_template_ram(struct brcms_hardware *wlc_hw, int offset, int len,
                            void *buf)
 {
-       struct d11regs __iomem *regs;
+       struct bcma_device *core = wlc_hw->d11core;
        u32 word;
        __le32 word_le;
        __be32 word_be;
        bool be_bit;
        BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
 
-       regs = wlc_hw->regs;
-       W_REG(&regs->tplatewrptr, offset);
+       bcma_write32(core, D11REGOFFS(tplatewrptr), offset);
 
        /* if MCTL_BIGEND bit set in mac control register,
         * the chip swaps data in fifo, as well as data in
         * template ram
         */
-       be_bit = (R_REG(&regs->maccontrol) & MCTL_BIGEND) != 0;
+       be_bit = (bcma_read32(core, D11REGOFFS(maccontrol)) & MCTL_BIGEND) != 0;
 
        while (len > 0) {
                memcpy(&word, buf, sizeof(u32));
@@ -1514,7 +1532,7 @@ brcms_b_write_template_ram(struct brcms_hardware *wlc_hw, int offset, int len,
                        word = *(u32 *)&word_le;
                }
 
-               W_REG(&regs->tplatewrdata, word);
+               bcma_write32(core, D11REGOFFS(tplatewrdata), word);
 
                buf = (u8 *) buf + sizeof(u32);
                len -= sizeof(u32);
@@ -1525,18 +1543,20 @@ static void brcms_b_set_cwmin(struct brcms_hardware *wlc_hw, u16 newmin)
 {
        wlc_hw->band->CWmin = newmin;
 
-       W_REG(&wlc_hw->regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_CWMIN);
-       (void)R_REG(&wlc_hw->regs->objaddr);
-       W_REG(&wlc_hw->regs->objdata, newmin);
+       bcma_write32(wlc_hw->d11core, D11REGOFFS(objaddr),
+                    OBJADDR_SCR_SEL | S_DOT11_CWMIN);
+       (void)bcma_read32(wlc_hw->d11core, D11REGOFFS(objaddr));
+       bcma_write32(wlc_hw->d11core, D11REGOFFS(objdata), newmin);
 }
 
 static void brcms_b_set_cwmax(struct brcms_hardware *wlc_hw, u16 newmax)
 {
        wlc_hw->band->CWmax = newmax;
 
-       W_REG(&wlc_hw->regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_CWMAX);
-       (void)R_REG(&wlc_hw->regs->objaddr);
-       W_REG(&wlc_hw->regs->objdata, newmax);
+       bcma_write32(wlc_hw->d11core, D11REGOFFS(objaddr),
+                    OBJADDR_SCR_SEL | S_DOT11_CWMAX);
+       (void)bcma_read32(wlc_hw->d11core, D11REGOFFS(objaddr));
+       bcma_write32(wlc_hw->d11core, D11REGOFFS(objdata), newmax);
 }
 
 void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw)
@@ -1702,17 +1722,17 @@ void brcms_b_core_phypll_reset(struct brcms_hardware *wlc_hw)
 {
        BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
 
-       ai_corereg(wlc_hw->sih, SI_CC_IDX,
-                  offsetof(struct chipcregs, chipcontrol_addr), ~0, 0);
+       ai_cc_reg(wlc_hw->sih, offsetof(struct chipcregs, chipcontrol_addr),
+                 ~0, 0);
        udelay(1);
-       ai_corereg(wlc_hw->sih, SI_CC_IDX,
-                  offsetof(struct chipcregs, chipcontrol_data), 0x4, 0);
+       ai_cc_reg(wlc_hw->sih, offsetof(struct chipcregs, chipcontrol_data),
+                 0x4, 0);
        udelay(1);
-       ai_corereg(wlc_hw->sih, SI_CC_IDX,
-                  offsetof(struct chipcregs, chipcontrol_data), 0x4, 4);
+       ai_cc_reg(wlc_hw->sih, offsetof(struct chipcregs, chipcontrol_data),
+                 0x4, 4);
        udelay(1);
-       ai_corereg(wlc_hw->sih, SI_CC_IDX,
-                  offsetof(struct chipcregs, chipcontrol_data), 0x4, 0);
+       ai_cc_reg(wlc_hw->sih, offsetof(struct chipcregs, chipcontrol_data),
+                 0x4, 0);
        udelay(1);
 }
 
@@ -1726,18 +1746,18 @@ void brcms_b_phyclk_fgc(struct brcms_hardware *wlc_hw, bool clk)
                return;
 
        if (ON == clk)
-               ai_core_cflags(wlc_hw->sih, SICF_FGC, SICF_FGC);
+               brcms_b_core_ioctl(wlc_hw, SICF_FGC, SICF_FGC);
        else
-               ai_core_cflags(wlc_hw->sih, SICF_FGC, 0);
+               brcms_b_core_ioctl(wlc_hw, SICF_FGC, 0);
 
 }
 
 void brcms_b_macphyclk_set(struct brcms_hardware *wlc_hw, bool clk)
 {
        if (ON == clk)
-               ai_core_cflags(wlc_hw->sih, SICF_MPCLKE, SICF_MPCLKE);
+               brcms_b_core_ioctl(wlc_hw, SICF_MPCLKE, SICF_MPCLKE);
        else
-               ai_core_cflags(wlc_hw->sih, SICF_MPCLKE, 0);
+               brcms_b_core_ioctl(wlc_hw, SICF_MPCLKE, 0);
 }
 
 void brcms_b_phy_reset(struct brcms_hardware *wlc_hw)
@@ -1757,7 +1777,7 @@ void brcms_b_phy_reset(struct brcms_hardware *wlc_hw)
        if (BRCMS_ISNPHY(wlc_hw->band) && NREV_GE(wlc_hw->band->phyrev, 3) &&
            NREV_LE(wlc_hw->band->phyrev, 4)) {
                /* Set the PHY bandwidth */
-               ai_core_cflags(wlc_hw->sih, SICF_BWMASK, phy_bw_clkbits);
+               brcms_b_core_ioctl(wlc_hw, SICF_BWMASK, phy_bw_clkbits);
 
                udelay(1);
 
@@ -1765,13 +1785,13 @@ void brcms_b_phy_reset(struct brcms_hardware *wlc_hw)
                brcms_b_core_phypll_reset(wlc_hw);
 
                /* reset the PHY */
-               ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_PCLKE),
-                              (SICF_PRST | SICF_PCLKE));
+               brcms_b_core_ioctl(wlc_hw, (SICF_PRST | SICF_PCLKE),
+                                  (SICF_PRST | SICF_PCLKE));
                phy_in_reset = true;
        } else {
-               ai_core_cflags(wlc_hw->sih,
-                              (SICF_PRST | SICF_PCLKE | SICF_BWMASK),
-                              (SICF_PRST | SICF_PCLKE | phy_bw_clkbits));
+               brcms_b_core_ioctl(wlc_hw,
+                                  (SICF_PRST | SICF_PCLKE | SICF_BWMASK),
+                                  (SICF_PRST | SICF_PCLKE | phy_bw_clkbits));
        }
 
        udelay(2);
@@ -1788,8 +1808,8 @@ static void brcms_b_setband(struct brcms_hardware *wlc_hw, uint bandunit,
        u32 macintmask;
 
        /* Enable the d11 core before accessing it */
-       if (!ai_iscoreup(wlc_hw->sih)) {
-               ai_core_reset(wlc_hw->sih, 0, 0);
+       if (!bcma_core_is_enabled(wlc_hw->d11core)) {
+               bcma_core_enable(wlc_hw->d11core, 0);
                brcms_c_mctrl_reset(wlc_hw);
        }
 
@@ -1815,7 +1835,8 @@ static void brcms_b_setband(struct brcms_hardware *wlc_hw, uint bandunit,
        brcms_intrsrestore(wlc->wl, macintmask);
 
        /* ucode should still be suspended.. */
-       WARN_ON((R_REG(&wlc_hw->regs->maccontrol) & MCTL_EN_MAC) != 0);
+       WARN_ON((bcma_read32(wlc_hw->d11core, D11REGOFFS(maccontrol)) &
+                MCTL_EN_MAC) != 0);
 }
 
 static bool brcms_c_isgoodchip(struct brcms_hardware *wlc_hw)
@@ -1843,7 +1864,7 @@ static bool brcms_c_validboardtype(struct brcms_hardware *wlc_hw)
        uint b2 = boardrev & 0xf;
 
        /* voards from other vendors are always considered valid */
-       if (wlc_hw->sih->boardvendor != PCI_VENDOR_ID_BROADCOM)
+       if (ai_get_boardvendor(wlc_hw->sih) != PCI_VENDOR_ID_BROADCOM)
                return true;
 
        /* do some boardrev sanity checks when boardvendor is Broadcom */
@@ -1915,7 +1936,7 @@ static void brcms_b_xtal(struct brcms_hardware *wlc_hw, bool want)
 static bool brcms_b_radio_read_hwdisabled(struct brcms_hardware *wlc_hw)
 {
        bool v, clk, xtal;
-       u32 resetbits = 0, flags = 0;
+       u32 flags = 0;
 
        xtal = wlc_hw->sbclk;
        if (!xtal)
@@ -1932,22 +1953,22 @@ static bool brcms_b_radio_read_hwdisabled(struct brcms_hardware *wlc_hw)
                flags |= SICF_PCLKE;
 
                /*
+                * TODO: test suspend/resume
+                *
                 * AI chip doesn't restore bar0win2 on
                 * hibernation/resume, need sw fixup
                 */
-               if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) ||
-                   (wlc_hw->sih->chip == BCM43225_CHIP_ID))
-                       wlc_hw->regs = (struct d11regs __iomem *)
-                                       ai_setcore(wlc_hw->sih, D11_CORE_ID, 0);
-               ai_core_reset(wlc_hw->sih, flags, resetbits);
+
+               bcma_core_enable(wlc_hw->d11core, flags);
                brcms_c_mctrl_reset(wlc_hw);
        }
 
-       v = ((R_REG(&wlc_hw->regs->phydebug) & PDBG_RFD) != 0);
+       v = ((bcma_read32(wlc_hw->d11core,
+                         D11REGOFFS(phydebug)) & PDBG_RFD) != 0);
 
        /* put core back into reset */
        if (!clk)
-               ai_core_disable(wlc_hw->sih, 0);
+               bcma_core_disable(wlc_hw->d11core, 0);
 
        if (!xtal)
                brcms_b_xtal(wlc_hw, OFF);
@@ -1971,25 +1992,21 @@ static bool wlc_dma_rxreset(struct brcms_hardware *wlc_hw, uint fifo)
  */
 void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags)
 {
-       struct d11regs __iomem *regs;
        uint i;
        bool fastclk;
-       u32 resetbits = 0;
 
        if (flags == BRCMS_USE_COREFLAGS)
                flags = (wlc_hw->band->pi ? wlc_hw->band->core_flags : 0);
 
        BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
 
-       regs = wlc_hw->regs;
-
        /* request FAST clock if not on  */
        fastclk = wlc_hw->forcefastclk;
        if (!fastclk)
                brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
 
        /* reset the dma engines except first time thru */
-       if (ai_iscoreup(wlc_hw->sih)) {
+       if (bcma_core_is_enabled(wlc_hw->d11core)) {
                for (i = 0; i < NFIFO; i++)
                        if ((wlc_hw->di[i]) && (!dma_txreset(wlc_hw->di[i])))
                                wiphy_err(wlc_hw->wlc->wiphy, "wl%d: %s: "
@@ -2027,14 +2044,14 @@ void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags)
         * they may touch chipcommon as well.
         */
        wlc_hw->clk = false;
-       ai_core_reset(wlc_hw->sih, flags, resetbits);
+       bcma_core_enable(wlc_hw->d11core, flags);
        wlc_hw->clk = true;
        if (wlc_hw->band && wlc_hw->band->pi)
                wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, true);
 
        brcms_c_mctrl_reset(wlc_hw);
 
-       if (wlc_hw->sih->cccaps & CC_CAP_PMU)
+       if (ai_get_cccaps(wlc_hw->sih) & CC_CAP_PMU)
                brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
 
        brcms_b_phy_reset(wlc_hw);
@@ -2055,7 +2072,7 @@ void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags)
  */
 static void brcms_b_corerev_fifofixup(struct brcms_hardware *wlc_hw)
 {
-       struct d11regs __iomem *regs = wlc_hw->regs;
+       struct bcma_device *core = wlc_hw->d11core;
        u16 fifo_nu;
        u16 txfifo_startblk = TXFIFO_START_BLK, txfifo_endblk;
        u16 txfifo_def, txfifo_def1;
@@ -2076,11 +2093,11 @@ static void brcms_b_corerev_fifofixup(struct brcms_hardware *wlc_hw)
                txfifo_cmd =
                    TXFIFOCMD_RESET_MASK | (fifo_nu << TXFIFOCMD_FIFOSEL_SHIFT);
 
-               W_REG(&regs->xmtfifocmd, txfifo_cmd);
-               W_REG(&regs->xmtfifodef, txfifo_def);
-               W_REG(&regs->xmtfifodef1, txfifo_def1);
+               bcma_write16(core, D11REGOFFS(xmtfifocmd), txfifo_cmd);
+               bcma_write16(core, D11REGOFFS(xmtfifodef), txfifo_def);
+               bcma_write16(core, D11REGOFFS(xmtfifodef1), txfifo_def1);
 
-               W_REG(&regs->xmtfifocmd, txfifo_cmd);
+               bcma_write16(core, D11REGOFFS(xmtfifocmd), txfifo_cmd);
 
                txfifo_startblk += wlc_hw->xmtfifo_sz[fifo_nu];
        }
@@ -2115,27 +2132,27 @@ static void brcms_b_corerev_fifofixup(struct brcms_hardware *wlc_hw)
 
 void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode)
 {
-       struct d11regs __iomem *regs = wlc_hw->regs;
+       struct bcma_device *core = wlc_hw->d11core;
 
-       if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) ||
-           (wlc_hw->sih->chip == BCM43225_CHIP_ID)) {
+       if ((ai_get_chip_id(wlc_hw->sih) == BCM43224_CHIP_ID) ||
+           (ai_get_chip_id(wlc_hw->sih) == BCM43225_CHIP_ID)) {
                if (spurmode == WL_SPURAVOID_ON2) {     /* 126Mhz */
-                       W_REG(&regs->tsf_clk_frac_l, 0x2082);
-                       W_REG(&regs->tsf_clk_frac_h, 0x8);
+                       bcma_write16(core, D11REGOFFS(tsf_clk_frac_l), 0x2082);
+                       bcma_write16(core, D11REGOFFS(tsf_clk_frac_h), 0x8);
                } else if (spurmode == WL_SPURAVOID_ON1) {      /* 123Mhz */
-                       W_REG(&regs->tsf_clk_frac_l, 0x5341);
-                       W_REG(&regs->tsf_clk_frac_h, 0x8);
+                       bcma_write16(core, D11REGOFFS(tsf_clk_frac_l), 0x5341);
+                       bcma_write16(core, D11REGOFFS(tsf_clk_frac_h), 0x8);
                } else {        /* 120Mhz */
-                       W_REG(&regs->tsf_clk_frac_l, 0x8889);
-                       W_REG(&regs->tsf_clk_frac_h, 0x8);
+                       bcma_write16(core, D11REGOFFS(tsf_clk_frac_l), 0x8889);
+                       bcma_write16(core, D11REGOFFS(tsf_clk_frac_h), 0x8);
                }
        } else if (BRCMS_ISLCNPHY(wlc_hw->band)) {
                if (spurmode == WL_SPURAVOID_ON1) {     /* 82Mhz */
-                       W_REG(&regs->tsf_clk_frac_l, 0x7CE0);
-                       W_REG(&regs->tsf_clk_frac_h, 0xC);
+                       bcma_write16(core, D11REGOFFS(tsf_clk_frac_l), 0x7CE0);
+                       bcma_write16(core, D11REGOFFS(tsf_clk_frac_h), 0xC);
                } else {        /* 80Mhz */
-                       W_REG(&regs->tsf_clk_frac_l, 0xCCCD);
-                       W_REG(&regs->tsf_clk_frac_h, 0xC);
+                       bcma_write16(core, D11REGOFFS(tsf_clk_frac_l), 0xCCCD);
+                       bcma_write16(core, D11REGOFFS(tsf_clk_frac_h), 0xC);
                }
        }
 }
@@ -2144,11 +2161,8 @@ void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode)
 static void brcms_c_gpio_init(struct brcms_c_info *wlc)
 {
        struct brcms_hardware *wlc_hw = wlc->hw;
-       struct d11regs __iomem *regs;
        u32 gc, gm;
 
-       regs = wlc_hw->regs;
-
        /* use GPIO select 0 to get all gpio signals from the gpio out reg */
        brcms_b_mctrl(wlc_hw, MCTL_GPOUT_SEL_MASK, 0);
 
@@ -2179,10 +2193,10 @@ static void brcms_c_gpio_init(struct brcms_c_info *wlc)
                 * The board itself is powered by these GPIOs
                 * (when not sending pattern) so set them high
                 */
-               OR_REG(&regs->psm_gpio_oe,
-                      (BOARD_GPIO_12 | BOARD_GPIO_13));
-               OR_REG(&regs->psm_gpio_out,
-                      (BOARD_GPIO_12 | BOARD_GPIO_13));
+               bcma_set16(wlc_hw->d11core, D11REGOFFS(psm_gpio_oe),
+                          (BOARD_GPIO_12 | BOARD_GPIO_13));
+               bcma_set16(wlc_hw->d11core, D11REGOFFS(psm_gpio_out),
+                          (BOARD_GPIO_12 | BOARD_GPIO_13));
 
                /* Enable antenna diversity, use 2x4 mode */
                brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN,
@@ -2209,7 +2223,7 @@ static void brcms_c_gpio_init(struct brcms_c_info *wlc)
 static void brcms_ucode_write(struct brcms_hardware *wlc_hw,
                              const __le32 ucode[], const size_t nbytes)
 {
-       struct d11regs __iomem *regs = wlc_hw->regs;
+       struct bcma_device *core = wlc_hw->d11core;
        uint i;
        uint count;
 
@@ -2217,10 +2231,11 @@ static void brcms_ucode_write(struct brcms_hardware *wlc_hw,
 
        count = (nbytes / sizeof(u32));
 
-       W_REG(&regs->objaddr, (OBJADDR_AUTO_INC | OBJADDR_UCM_SEL));
-       (void)R_REG(&regs->objaddr);
+       bcma_write32(core, D11REGOFFS(objaddr),
+                    OBJADDR_AUTO_INC | OBJADDR_UCM_SEL);
+       (void)bcma_read32(core, D11REGOFFS(objaddr));
        for (i = 0; i < count; i++)
-               W_REG(&regs->objdata, le32_to_cpu(ucode[i]));
+               bcma_write32(core, D11REGOFFS(objdata), le32_to_cpu(ucode[i]));
 
 }
 
@@ -2286,7 +2301,7 @@ static void brcms_b_fifoerrors(struct brcms_hardware *wlc_hw)
        bool fatal = false;
        uint unit;
        uint intstatus, idx;
-       struct d11regs __iomem *regs = wlc_hw->regs;
+       struct bcma_device *core = wlc_hw->d11core;
        struct wiphy *wiphy = wlc_hw->wlc->wiphy;
 
        unit = wlc_hw->unit;
@@ -2294,7 +2309,9 @@ static void brcms_b_fifoerrors(struct brcms_hardware *wlc_hw)
        for (idx = 0; idx < NFIFO; idx++) {
                /* read intstatus register and ignore any non-error bits */
                intstatus =
-                   R_REG(&regs->intctrlregs[idx].intstatus) & I_ERRORS;
+                       bcma_read32(core,
+                                   D11REGOFFS(intctrlregs[idx].intstatus)) &
+                       I_ERRORS;
                if (!intstatus)
                        continue;
 
@@ -2339,8 +2356,9 @@ static void brcms_b_fifoerrors(struct brcms_hardware *wlc_hw)
                        brcms_fatal_error(wlc_hw->wlc->wl); /* big hammer */
                        break;
                } else
-                       W_REG(&regs->intctrlregs[idx].intstatus,
-                             intstatus);
+                       bcma_write32(core,
+                                    D11REGOFFS(intctrlregs[idx].intstatus),
+                                    intstatus);
        }
 }
 
@@ -2348,28 +2366,7 @@ void brcms_c_intrson(struct brcms_c_info *wlc)
 {
        struct brcms_hardware *wlc_hw = wlc->hw;
        wlc->macintmask = wlc->defmacintmask;
-       W_REG(&wlc_hw->regs->macintmask, wlc->macintmask);
-}
-
-/*
- * callback for siutils.c, which has only wlc handler, no wl they both check
- * up, not only because there is no need to off/restore d11 interrupt but also
- * because per-port code may require sync with valid interrupt.
- */
-static u32 brcms_c_wlintrsoff(struct brcms_c_info *wlc)
-{
-       if (!wlc->hw->up)
-               return 0;
-
-       return brcms_intrsoff(wlc->wl);
-}
-
-static void brcms_c_wlintrsrestore(struct brcms_c_info *wlc, u32 macintmask)
-{
-       if (!wlc->hw->up)
-               return;
-
-       brcms_intrsrestore(wlc->wl, macintmask);
+       bcma_write32(wlc_hw->d11core, D11REGOFFS(macintmask), wlc->macintmask);
 }
 
 u32 brcms_c_intrsoff(struct brcms_c_info *wlc)
@@ -2382,8 +2379,8 @@ u32 brcms_c_intrsoff(struct brcms_c_info *wlc)
 
        macintmask = wlc->macintmask;   /* isr can still happen */
 
-       W_REG(&wlc_hw->regs->macintmask, 0);
-       (void)R_REG(&wlc_hw->regs->macintmask); /* sync readback */
+       bcma_write32(wlc_hw->d11core, D11REGOFFS(macintmask), 0);
+       (void)bcma_read32(wlc_hw->d11core, D11REGOFFS(macintmask));
        udelay(1);              /* ensure int line is no longer driven */
        wlc->macintmask = 0;
 
@@ -2398,7 +2395,7 @@ void brcms_c_intrsrestore(struct brcms_c_info *wlc, u32 macintmask)
                return;
 
        wlc->macintmask = macintmask;
-       W_REG(&wlc_hw->regs->macintmask, wlc->macintmask);
+       bcma_write32(wlc_hw->d11core, D11REGOFFS(macintmask), wlc->macintmask);
 }
 
 /* assumes that the d11 MAC is enabled */
@@ -2510,11 +2507,11 @@ brcms_c_mute(struct brcms_c_info *wlc, bool mute_tx)
 static inline u32 wlc_intstatus(struct brcms_c_info *wlc, bool in_isr)
 {
        struct brcms_hardware *wlc_hw = wlc->hw;
-       struct d11regs __iomem *regs = wlc_hw->regs;
+       struct bcma_device *core = wlc_hw->d11core;
        u32 macintstatus;
 
        /* macintstatus includes a DMA interrupt summary bit */
-       macintstatus = R_REG(&regs->macintstatus);
+       macintstatus = bcma_read32(core, D11REGOFFS(macintstatus));
 
        BCMMSG(wlc->wiphy, "wl%d: macintstatus: 0x%x\n", wlc_hw->unit,
                 macintstatus);
@@ -2541,12 +2538,12 @@ static inline u32 wlc_intstatus(struct brcms_c_info *wlc, bool in_isr)
         * consequences
         */
        /* turn off the interrupts */
-       W_REG(&regs->macintmask, 0);
-       (void)R_REG(&regs->macintmask); /* sync readback */
+       bcma_write32(core, D11REGOFFS(macintmask), 0);
+       (void)bcma_read32(core, D11REGOFFS(macintmask));
        wlc->macintmask = 0;
 
        /* clear device interrupts */
-       W_REG(&regs->macintstatus, macintstatus);
+       bcma_write32(core, D11REGOFFS(macintstatus), macintstatus);
 
        /* MI_DMAINT is indication of non-zero intstatus */
        if (macintstatus & MI_DMAINT)
@@ -2555,8 +2552,8 @@ static inline u32 wlc_intstatus(struct brcms_c_info *wlc, bool in_isr)
                 * RX_FIFO. If MI_DMAINT is set, assume it
                 * is set and clear the interrupt.
                 */
-               W_REG(&regs->intctrlregs[RX_FIFO].intstatus,
-                     DEF_RXINTMASK);
+               bcma_write32(core, D11REGOFFS(intctrlregs[RX_FIFO].intstatus),
+                            DEF_RXINTMASK);
 
        return macintstatus;
 }
@@ -2619,7 +2616,7 @@ bool brcms_c_isr(struct brcms_c_info *wlc, bool *wantdpc)
 void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc)
 {
        struct brcms_hardware *wlc_hw = wlc->hw;
-       struct d11regs __iomem *regs = wlc_hw->regs;
+       struct bcma_device *core = wlc_hw->d11core;
        u32 mc, mi;
        struct wiphy *wiphy = wlc->wiphy;
 
@@ -2636,7 +2633,7 @@ void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc)
        /* force the core awake */
        brcms_c_ucode_wake_override_set(wlc_hw, BRCMS_WAKE_OVERRIDE_MACSUSPEND);
 
-       mc = R_REG(&regs->maccontrol);
+       mc = bcma_read32(core, D11REGOFFS(maccontrol));
 
        if (mc == 0xffffffff) {
                wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
@@ -2648,7 +2645,7 @@ void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc)
        WARN_ON(!(mc & MCTL_PSM_RUN));
        WARN_ON(!(mc & MCTL_EN_MAC));
 
-       mi = R_REG(&regs->macintstatus);
+       mi = bcma_read32(core, D11REGOFFS(macintstatus));
        if (mi == 0xffffffff) {
                wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
                          __func__);
@@ -2659,21 +2656,21 @@ void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc)
 
        brcms_b_mctrl(wlc_hw, MCTL_EN_MAC, 0);
 
-       SPINWAIT(!(R_REG(&regs->macintstatus) & MI_MACSSPNDD),
+       SPINWAIT(!(bcma_read32(core, D11REGOFFS(macintstatus)) & MI_MACSSPNDD),
                 BRCMS_MAX_MAC_SUSPEND);
 
-       if (!(R_REG(&regs->macintstatus) & MI_MACSSPNDD)) {
+       if (!(bcma_read32(core, D11REGOFFS(macintstatus)) & MI_MACSSPNDD)) {
                wiphy_err(wiphy, "wl%d: wlc_suspend_mac_and_wait: waited %d uS"
                          " and MI_MACSSPNDD is still not on.\n",
                          wlc_hw->unit, BRCMS_MAX_MAC_SUSPEND);
                wiphy_err(wiphy, "wl%d: psmdebug 0x%08x, phydebug 0x%08x, "
                          "psm_brc 0x%04x\n", wlc_hw->unit,
-                         R_REG(&regs->psmdebug),
-                         R_REG(&regs->phydebug),
-                         R_REG(&regs->psm_brc));
+                         bcma_read32(core, D11REGOFFS(psmdebug)),
+                         bcma_read32(core, D11REGOFFS(phydebug)),
+                         bcma_read16(core, D11REGOFFS(psm_brc)));
        }
 
-       mc = R_REG(&regs->maccontrol);
+       mc = bcma_read32(core, D11REGOFFS(maccontrol));
        if (mc == 0xffffffff) {
                wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
                          __func__);
@@ -2688,7 +2685,7 @@ void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc)
 void brcms_c_enable_mac(struct brcms_c_info *wlc)
 {
        struct brcms_hardware *wlc_hw = wlc->hw;
-       struct d11regs __iomem *regs = wlc_hw->regs;
+       struct bcma_device *core = wlc_hw->d11core;
        u32 mc, mi;
 
        BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
@@ -2701,20 +2698,20 @@ void brcms_c_enable_mac(struct brcms_c_info *wlc)
        if (wlc_hw->mac_suspend_depth > 0)
                return;
 
-       mc = R_REG(&regs->maccontrol);
+       mc = bcma_read32(core, D11REGOFFS(maccontrol));
        WARN_ON(mc & MCTL_PSM_JMP_0);
        WARN_ON(mc & MCTL_EN_MAC);
        WARN_ON(!(mc & MCTL_PSM_RUN));
 
        brcms_b_mctrl(wlc_hw, MCTL_EN_MAC, MCTL_EN_MAC);
-       W_REG(&regs->macintstatus, MI_MACSSPNDD);
+       bcma_write32(core, D11REGOFFS(macintstatus), MI_MACSSPNDD);
 
-       mc = R_REG(&regs->maccontrol);
+       mc = bcma_read32(core, D11REGOFFS(maccontrol));
        WARN_ON(mc & MCTL_PSM_JMP_0);
        WARN_ON(!(mc & MCTL_EN_MAC));
        WARN_ON(!(mc & MCTL_PSM_RUN));
 
-       mi = R_REG(&regs->macintstatus);
+       mi = bcma_read32(core, D11REGOFFS(macintstatus));
        WARN_ON(mi & MI_MACSSPNDD);
 
        brcms_c_ucode_wake_override_clear(wlc_hw,
@@ -2731,55 +2728,53 @@ void brcms_b_band_stf_ss_set(struct brcms_hardware *wlc_hw, u8 stf_mode)
 
 static bool brcms_b_validate_chip_access(struct brcms_hardware *wlc_hw)
 {
-       struct d11regs __iomem *regs;
+       struct bcma_device *core = wlc_hw->d11core;
        u32 w, val;
        struct wiphy *wiphy = wlc_hw->wlc->wiphy;
 
        BCMMSG(wiphy, "wl%d\n", wlc_hw->unit);
 
-       regs = wlc_hw->regs;
-
        /* Validate dchip register access */
 
-       W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
-       (void)R_REG(&regs->objaddr);
-       w = R_REG(&regs->objdata);
+       bcma_write32(core, D11REGOFFS(objaddr), OBJADDR_SHM_SEL | 0);
+       (void)bcma_read32(core, D11REGOFFS(objaddr));
+       w = bcma_read32(core, D11REGOFFS(objdata));
 
        /* Can we write and read back a 32bit register? */
-       W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
-       (void)R_REG(&regs->objaddr);
-       W_REG(&regs->objdata, (u32) 0xaa5555aa);
+       bcma_write32(core, D11REGOFFS(objaddr), OBJADDR_SHM_SEL | 0);
+       (void)bcma_read32(core, D11REGOFFS(objaddr));
+       bcma_write32(core, D11REGOFFS(objdata), (u32) 0xaa5555aa);
 
-       W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
-       (void)R_REG(&regs->objaddr);
-       val = R_REG(&regs->objdata);
+       bcma_write32(core, D11REGOFFS(objaddr), OBJADDR_SHM_SEL | 0);
+       (void)bcma_read32(core, D11REGOFFS(objaddr));
+       val = bcma_read32(core, D11REGOFFS(objdata));
        if (val != (u32) 0xaa5555aa) {
                wiphy_err(wiphy, "wl%d: validate_chip_access: SHM = 0x%x, "
                          "expected 0xaa5555aa\n", wlc_hw->unit, val);
                return false;
        }
 
-       W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
-       (void)R_REG(&regs->objaddr);
-       W_REG(&regs->objdata, (u32) 0x55aaaa55);
+       bcma_write32(core, D11REGOFFS(objaddr), OBJADDR_SHM_SEL | 0);
+       (void)bcma_read32(core, D11REGOFFS(objaddr));
+       bcma_write32(core, D11REGOFFS(objdata), (u32) 0x55aaaa55);
 
-       W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
-       (void)R_REG(&regs->objaddr);
-       val = R_REG(&regs->objdata);
+       bcma_write32(core, D11REGOFFS(objaddr), OBJADDR_SHM_SEL | 0);
+       (void)bcma_read32(core, D11REGOFFS(objaddr));
+       val = bcma_read32(core, D11REGOFFS(objdata));
        if (val != (u32) 0x55aaaa55) {
                wiphy_err(wiphy, "wl%d: validate_chip_access: SHM = 0x%x, "
                          "expected 0x55aaaa55\n", wlc_hw->unit, val);
                return false;
        }
 
-       W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
-       (void)R_REG(&regs->objaddr);
-       W_REG(&regs->objdata, w);
+       bcma_write32(core, D11REGOFFS(objaddr), OBJADDR_SHM_SEL | 0);
+       (void)bcma_read32(core, D11REGOFFS(objaddr));
+       bcma_write32(core, D11REGOFFS(objdata), w);
 
        /* clear CFPStart */
-       W_REG(&regs->tsf_cfpstart, 0);
+       bcma_write32(core, D11REGOFFS(tsf_cfpstart), 0);
 
-       w = R_REG(&regs->maccontrol);
+       w = bcma_read32(core, D11REGOFFS(maccontrol));
        if ((w != (MCTL_IHR_EN | MCTL_WAKE)) &&
            (w != (MCTL_IHR_EN | MCTL_GMODE | MCTL_WAKE))) {
                wiphy_err(wiphy, "wl%d: validate_chip_access: maccontrol = "
@@ -2796,38 +2791,38 @@ static bool brcms_b_validate_chip_access(struct brcms_hardware *wlc_hw)
 
 void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on)
 {
-       struct d11regs __iomem *regs;
+       struct bcma_device *core = wlc_hw->d11core;
        u32 tmp;
 
        BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
 
        tmp = 0;
-       regs = wlc_hw->regs;
 
        if (on) {
-               if ((wlc_hw->sih->chip == BCM4313_CHIP_ID)) {
-                       OR_REG(&regs->clk_ctl_st,
-                              (CCS_ERSRC_REQ_HT | CCS_ERSRC_REQ_D11PLL |
-                               CCS_ERSRC_REQ_PHYPLL));
-                       SPINWAIT((R_REG(&regs->clk_ctl_st) &
-                                 (CCS_ERSRC_AVAIL_HT)) != (CCS_ERSRC_AVAIL_HT),
+               if ((ai_get_chip_id(wlc_hw->sih) == BCM4313_CHIP_ID)) {
+                       bcma_set32(core, D11REGOFFS(clk_ctl_st),
+                                  CCS_ERSRC_REQ_HT |
+                                  CCS_ERSRC_REQ_D11PLL |
+                                  CCS_ERSRC_REQ_PHYPLL);
+                       SPINWAIT((bcma_read32(core, D11REGOFFS(clk_ctl_st)) &
+                                 CCS_ERSRC_AVAIL_HT) != CCS_ERSRC_AVAIL_HT,
                                 PHYPLL_WAIT_US);
 
-                       tmp = R_REG(&regs->clk_ctl_st);
-                       if ((tmp & (CCS_ERSRC_AVAIL_HT)) !=
-                           (CCS_ERSRC_AVAIL_HT))
+                       tmp = bcma_read32(core, D11REGOFFS(clk_ctl_st));
+                       if ((tmp & CCS_ERSRC_AVAIL_HT) != CCS_ERSRC_AVAIL_HT)
                                wiphy_err(wlc_hw->wlc->wiphy, "%s: turn on PHY"
                                          " PLL failed\n", __func__);
                } else {
-                       OR_REG(&regs->clk_ctl_st,
-                              (CCS_ERSRC_REQ_D11PLL | CCS_ERSRC_REQ_PHYPLL));
-                       SPINWAIT((R_REG(&regs->clk_ctl_st) &
+                       bcma_set32(core, D11REGOFFS(clk_ctl_st),
+                                  tmp | CCS_ERSRC_REQ_D11PLL |
+                                  CCS_ERSRC_REQ_PHYPLL);
+                       SPINWAIT((bcma_read32(core, D11REGOFFS(clk_ctl_st)) &
                                  (CCS_ERSRC_AVAIL_D11PLL |
                                   CCS_ERSRC_AVAIL_PHYPLL)) !=
                                 (CCS_ERSRC_AVAIL_D11PLL |
                                  CCS_ERSRC_AVAIL_PHYPLL), PHYPLL_WAIT_US);
 
-                       tmp = R_REG(&regs->clk_ctl_st);
+                       tmp = bcma_read32(core, D11REGOFFS(clk_ctl_st));
                        if ((tmp &
                             (CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL))
                            !=
@@ -2841,8 +2836,9 @@ void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on)
                 * be requesting it; so we'll deassert the request but
                 * not wait for status to comply.
                 */
-               AND_REG(&regs->clk_ctl_st, ~CCS_ERSRC_REQ_PHYPLL);
-               tmp = R_REG(&regs->clk_ctl_st);
+               bcma_mask32(core, D11REGOFFS(clk_ctl_st),
+                           ~CCS_ERSRC_REQ_PHYPLL);
+               (void)bcma_read32(core, D11REGOFFS(clk_ctl_st));
        }
 }
 
@@ -2870,7 +2866,7 @@ static void brcms_c_coredisable(struct brcms_hardware *wlc_hw)
        brcms_b_core_phypll_ctl(wlc_hw, false);
 
        wlc_hw->clk = false;
-       ai_core_disable(wlc_hw->sih, 0);
+       bcma_core_disable(wlc_hw->d11core, 0);
        wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false);
 }
 
@@ -2894,35 +2890,31 @@ static void brcms_c_flushqueues(struct brcms_c_info *wlc)
 static u16
 brcms_b_read_objmem(struct brcms_hardware *wlc_hw, uint offset, u32 sel)
 {
-       struct d11regs __iomem *regs = wlc_hw->regs;
-       u16 __iomem *objdata_lo = (u16 __iomem *)&regs->objdata;
-       u16 __iomem *objdata_hi = objdata_lo + 1;
-       u16 v;
+       struct bcma_device *core = wlc_hw->d11core;
+       u16 objoff = D11REGOFFS(objdata);
 
-       W_REG(&regs->objaddr, sel | (offset >> 2));
-       (void)R_REG(&regs->objaddr);
+       bcma_write32(core, D11REGOFFS(objaddr), sel | (offset >> 2));
+       (void)bcma_read32(core, D11REGOFFS(objaddr));
        if (offset & 2)
-               v = R_REG(objdata_hi);
-       else
-               v = R_REG(objdata_lo);
+               objoff += 2;
 
-       return v;
+       return bcma_read16(core, objoff);
+;
 }
 
 static void
 brcms_b_write_objmem(struct brcms_hardware *wlc_hw, uint offset, u16 v,
                     u32 sel)
 {
-       struct d11regs __iomem *regs = wlc_hw->regs;
-       u16 __iomem *objdata_lo = (u16 __iomem *)&regs->objdata;
-       u16 __iomem *objdata_hi = objdata_lo + 1;
+       struct bcma_device *core = wlc_hw->d11core;
+       u16 objoff = D11REGOFFS(objdata);
 
-       W_REG(&regs->objaddr, sel | (offset >> 2));
-       (void)R_REG(&regs->objaddr);
+       bcma_write32(core, D11REGOFFS(objaddr), sel | (offset >> 2));
+       (void)bcma_read32(core, D11REGOFFS(objaddr));
        if (offset & 2)
-               W_REG(objdata_hi, v);
-       else
-               W_REG(objdata_lo, v);
+               objoff += 2;
+
+       bcma_write16(core, objoff, v);
 }
 
 /*
@@ -3008,14 +3000,14 @@ static void brcms_b_retrylimit_upd(struct brcms_hardware *wlc_hw,
 
        /* write retry limit to SCR, shouldn't need to suspend */
        if (wlc_hw->up) {
-               W_REG(&wlc_hw->regs->objaddr,
-                     OBJADDR_SCR_SEL | S_DOT11_SRC_LMT);
-               (void)R_REG(&wlc_hw->regs->objaddr);
-               W_REG(&wlc_hw->regs->objdata, wlc_hw->SRL);
-               W_REG(&wlc_hw->regs->objaddr,
-                     OBJADDR_SCR_SEL | S_DOT11_LRC_LMT);
-               (void)R_REG(&wlc_hw->regs->objaddr);
-               W_REG(&wlc_hw->regs->objdata, wlc_hw->LRL);
+               bcma_write32(wlc_hw->d11core, D11REGOFFS(objaddr),
+                            OBJADDR_SCR_SEL | S_DOT11_SRC_LMT);
+               (void)bcma_read32(wlc_hw->d11core, D11REGOFFS(objaddr));
+               bcma_write32(wlc_hw->d11core, D11REGOFFS(objdata), wlc_hw->SRL);
+               bcma_write32(wlc_hw->d11core, D11REGOFFS(objaddr),
+                            OBJADDR_SCR_SEL | S_DOT11_LRC_LMT);
+               (void)bcma_read32(wlc_hw->d11core, D11REGOFFS(objaddr));
+               bcma_write32(wlc_hw->d11core, D11REGOFFS(objdata), wlc_hw->LRL);
        }
 }
 
@@ -3197,9 +3189,9 @@ void brcms_c_init_scb(struct scb *scb)
 static void brcms_b_coreinit(struct brcms_c_info *wlc)
 {
        struct brcms_hardware *wlc_hw = wlc->hw;
-       struct d11regs __iomem *regs;
+       struct bcma_device *core = wlc_hw->d11core;
        u32 sflags;
-       uint bcnint_us;
+       u32 bcnint_us;
        uint i = 0;
        bool fifosz_fixup = false;
        int err = 0;
@@ -3207,8 +3199,6 @@ static void brcms_b_coreinit(struct brcms_c_info *wlc)
        struct wiphy *wiphy = wlc->wiphy;
        struct brcms_ucode *ucode = &wlc_hw->wlc->wl->ucode;
 
-       regs = wlc_hw->regs;
-
        BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
 
        /* reset PSM */
@@ -3221,20 +3211,20 @@ static void brcms_b_coreinit(struct brcms_c_info *wlc)
        fifosz_fixup = true;
 
        /* let the PSM run to the suspended state, set mode to BSS STA */
-       W_REG(&regs->macintstatus, -1);
+       bcma_write32(core, D11REGOFFS(macintstatus), -1);
        brcms_b_mctrl(wlc_hw, ~0,
                       (MCTL_IHR_EN | MCTL_INFRA | MCTL_PSM_RUN | MCTL_WAKE));
 
        /* wait for ucode to self-suspend after auto-init */
-       SPINWAIT(((R_REG(&regs->macintstatus) & MI_MACSSPNDD) == 0),
-                1000 * 1000);
-       if ((R_REG(&regs->macintstatus) & MI_MACSSPNDD) == 0)
+       SPINWAIT(((bcma_read32(core, D11REGOFFS(macintstatus)) &
+                  MI_MACSSPNDD) == 0), 1000 * 1000);
+       if ((bcma_read32(core, D11REGOFFS(macintstatus)) & MI_MACSSPNDD) == 0)
                wiphy_err(wiphy, "wl%d: wlc_coreinit: ucode did not self-"
                          "suspend!\n", wlc_hw->unit);
 
        brcms_c_gpio_init(wlc);
 
-       sflags = ai_core_sflags(wlc_hw->sih, 0, 0);
+       sflags = bcma_aread32(core, BCMA_IOST);
 
        if (D11REV_IS(wlc_hw->corerev, 23)) {
                if (BRCMS_ISNPHY(wlc_hw->band))
@@ -3298,7 +3288,7 @@ static void brcms_b_coreinit(struct brcms_c_info *wlc)
                          wlc_hw->xmtfifo_sz[i], i);
 
        /* make sure we can still talk to the mac */
-       WARN_ON(R_REG(&regs->maccontrol) == 0xffffffff);
+       WARN_ON(bcma_read32(core, D11REGOFFS(maccontrol)) == 0xffffffff);
 
        /* band-specific inits done by wlc_bsinit() */
 
@@ -3307,7 +3297,7 @@ static void brcms_b_coreinit(struct brcms_c_info *wlc)
        brcms_b_write_shm(wlc_hw, M_MAX_ANTCNT, ANTCNT);
 
        /* enable one rx interrupt per received frame */
-       W_REG(&regs->intrcvlazy[0], (1 << IRL_FC_SHIFT));
+       bcma_write32(core, D11REGOFFS(intrcvlazy[0]), (1 << IRL_FC_SHIFT));
 
        /* set the station mode (BSS STA) */
        brcms_b_mctrl(wlc_hw,
@@ -3316,19 +3306,21 @@ static void brcms_b_coreinit(struct brcms_c_info *wlc)
 
        /* set up Beacon interval */
        bcnint_us = 0x8000 << 10;
-       W_REG(&regs->tsf_cfprep, (bcnint_us << CFPREP_CBI_SHIFT));
-       W_REG(&regs->tsf_cfpstart, bcnint_us);
-       W_REG(&regs->macintstatus, MI_GP1);
+       bcma_write32(core, D11REGOFFS(tsf_cfprep),
+                    (bcnint_us << CFPREP_CBI_SHIFT));
+       bcma_write32(core, D11REGOFFS(tsf_cfpstart), bcnint_us);
+       bcma_write32(core, D11REGOFFS(macintstatus), MI_GP1);
 
        /* write interrupt mask */
-       W_REG(&regs->intctrlregs[RX_FIFO].intmask, DEF_RXINTMASK);
+       bcma_write32(core, D11REGOFFS(intctrlregs[RX_FIFO].intmask),
+                    DEF_RXINTMASK);
 
        /* allow the MAC to control the PHY clock (dynamic on/off) */
        brcms_b_macphyclk_set(wlc_hw, ON);
 
        /* program dynamic clock control fast powerup delay register */
        wlc->fastpwrup_dly = ai_clkctl_fast_pwrup_delay(wlc_hw->sih);
-       W_REG(&regs->scc_fastpwrup_dly, wlc->fastpwrup_dly);
+       bcma_write16(core, D11REGOFFS(scc_fastpwrup_dly), wlc->fastpwrup_dly);
 
        /* tell the ucode the corerev */
        brcms_b_write_shm(wlc_hw, M_MACHW_VER, (u16) wlc_hw->corerev);
@@ -3341,19 +3333,21 @@ static void brcms_b_coreinit(struct brcms_c_info *wlc)
                                      machwcap >> 16) & 0xffff));
 
        /* write retry limits to SCR, this done after PSM init */
-       W_REG(&regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_SRC_LMT);
-       (void)R_REG(&regs->objaddr);
-       W_REG(&regs->objdata, wlc_hw->SRL);
-       W_REG(&regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_LRC_LMT);
-       (void)R_REG(&regs->objaddr);
-       W_REG(&regs->objdata, wlc_hw->LRL);
+       bcma_write32(core, D11REGOFFS(objaddr),
+                    OBJADDR_SCR_SEL | S_DOT11_SRC_LMT);
+       (void)bcma_read32(core, D11REGOFFS(objaddr));
+       bcma_write32(core, D11REGOFFS(objdata), wlc_hw->SRL);
+       bcma_write32(core, D11REGOFFS(objaddr),
+                    OBJADDR_SCR_SEL | S_DOT11_LRC_LMT);
+       (void)bcma_read32(core, D11REGOFFS(objaddr));
+       bcma_write32(core, D11REGOFFS(objdata), wlc_hw->LRL);
 
        /* write rate fallback retry limits */
        brcms_b_write_shm(wlc_hw, M_SFRMTXCNTFBRTHSD, wlc_hw->SFBL);
        brcms_b_write_shm(wlc_hw, M_LFRMTXCNTFBRTHSD, wlc_hw->LFBL);
 
-       AND_REG(&regs->ifs_ctl, 0x0FFF);
-       W_REG(&regs->ifs_aifsn, EDCF_AIFSN_MIN);
+       bcma_mask16(core, D11REGOFFS(ifs_ctl), 0x0FFF);
+       bcma_write16(core, D11REGOFFS(ifs_aifsn), EDCF_AIFSN_MIN);
 
        /* init the tx dma engines */
        for (i = 0; i < NFIFO; i++) {
@@ -3810,7 +3804,7 @@ static void brcms_c_set_ps_ctrl(struct brcms_c_info *wlc)
 
        BCMMSG(wlc->wiphy, "wl%d: hps %d\n", wlc->pub->unit, hps);
 
-       v1 = R_REG(&wlc->regs->maccontrol);
+       v1 = bcma_read32(wlc->hw->d11core, D11REGOFFS(maccontrol));
        v2 = MCTL_WAKE;
        if (hps)
                v2 |= MCTL_HPS;
@@ -4129,7 +4123,8 @@ void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci,
                acp_shm.cwmax = params->cw_max;
                acp_shm.cwcur = acp_shm.cwmin;
                acp_shm.bslots =
-                   R_REG(&wlc->regs->tsf_random) & acp_shm.cwcur;
+                       bcma_read16(wlc->hw->d11core, D11REGOFFS(tsf_random)) &
+                       acp_shm.cwcur;
                acp_shm.reggap = acp_shm.bslots + acp_shm.aifs;
                /* Indicate the new params to the ucode */
                acp_shm.status = brcms_b_read_shm(wlc->hw, (M_EDCF_QINFO +
@@ -4437,21 +4432,21 @@ struct brcms_pub *brcms_c_pub(struct brcms_c_info *wlc)
  *    initialize software state for each core and band
  *    put the whole chip in reset(driver down state), no clock
  */
-static int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device,
-                         uint unit, bool piomode, void __iomem *regsva,
-                         struct pci_dev *btparam)
+static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core,
+                         uint unit, bool piomode)
 {
        struct brcms_hardware *wlc_hw;
-       struct d11regs __iomem *regs;
        char *macaddr = NULL;
        uint err = 0;
        uint j;
        bool wme = false;
        struct shared_phy_params sha_params;
        struct wiphy *wiphy = wlc->wiphy;
+       struct pci_dev *pcidev = core->bus->host_pci;
 
-       BCMMSG(wlc->wiphy, "wl%d: vendor 0x%x device 0x%x\n", unit, vendor,
-               device);
+       BCMMSG(wlc->wiphy, "wl%d: vendor 0x%x device 0x%x\n", unit,
+              pcidev->vendor,
+              pcidev->device);
 
        wme = true;
 
@@ -4468,7 +4463,7 @@ static int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device,
         * Do the hardware portion of the attach. Also initialize software
         * state that depends on the particular hardware we are running.
         */
-       wlc_hw->sih = ai_attach(regsva, btparam);
+       wlc_hw->sih = ai_attach(core->bus);
        if (wlc_hw->sih == NULL) {
                wiphy_err(wiphy, "wl%d: brcms_b_attach: si_attach failed\n",
                          unit);
@@ -4477,25 +4472,19 @@ static int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device,
        }
 
        /* verify again the device is supported */
-       if (!brcms_c_chipmatch(vendor, device)) {
+       if (!brcms_c_chipmatch(pcidev->vendor, pcidev->device)) {
                wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported "
                        "vendor/device (0x%x/0x%x)\n",
-                        unit, vendor, device);
+                        unit, pcidev->vendor, pcidev->device);
                err = 12;
                goto fail;
        }
 
-       wlc_hw->vendorid = vendor;
-       wlc_hw->deviceid = device;
+       wlc_hw->vendorid = pcidev->vendor;
+       wlc_hw->deviceid = pcidev->device;
 
-       /* set bar0 window to point at D11 core */
-       wlc_hw->regs = (struct d11regs __iomem *)
-                               ai_setcore(wlc_hw->sih, D11_CORE_ID, 0);
-       wlc_hw->corerev = ai_corerev(wlc_hw->sih);
-
-       regs = wlc_hw->regs;
-
-       wlc->regs = wlc_hw->regs;
+       wlc_hw->d11core = core;
+       wlc_hw->corerev = core->id.rev;
 
        /* validate chip, chiprev and corerev */
        if (!brcms_c_isgoodchip(wlc_hw)) {
@@ -4530,8 +4519,9 @@ static int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device,
        wlc_hw->boardrev = (u16) j;
        if (!brcms_c_validboardtype(wlc_hw)) {
                wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported Broadcom "
-                       "board type (0x%x)" " or revision level (0x%x)\n",
-                        unit, wlc_hw->sih->boardtype, wlc_hw->boardrev);
+                         "board type (0x%x)" " or revision level (0x%x)\n",
+                         unit, ai_get_boardtype(wlc_hw->sih),
+                         wlc_hw->boardrev);
                err = 15;
                goto fail;
        }
@@ -4552,7 +4542,7 @@ static int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device,
        else
                wlc_hw->_nbands = 1;
 
-       if ((wlc_hw->sih->chip == BCM43225_CHIP_ID))
+       if ((ai_get_chip_id(wlc_hw->sih) == BCM43225_CHIP_ID))
                wlc_hw->_nbands = 1;
 
        /* BMAC_NOTE: remove init of pub values when brcms_c_attach()
@@ -4584,16 +4574,14 @@ static int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device,
        sha_params.corerev = wlc_hw->corerev;
        sha_params.vid = wlc_hw->vendorid;
        sha_params.did = wlc_hw->deviceid;
-       sha_params.chip = wlc_hw->sih->chip;
-       sha_params.chiprev = wlc_hw->sih->chiprev;
-       sha_params.chippkg = wlc_hw->sih->chippkg;
+       sha_params.chip = ai_get_chip_id(wlc_hw->sih);
+       sha_params.chiprev = ai_get_chiprev(wlc_hw->sih);
+       sha_params.chippkg = ai_get_chippkg(wlc_hw->sih);
        sha_params.sromrev = wlc_hw->sromrev;
-       sha_params.boardtype = wlc_hw->sih->boardtype;
+       sha_params.boardtype = ai_get_boardtype(wlc_hw->sih);
        sha_params.boardrev = wlc_hw->boardrev;
-       sha_params.boardvendor = wlc_hw->sih->boardvendor;
        sha_params.boardflags = wlc_hw->boardflags;
        sha_params.boardflags2 = wlc_hw->boardflags2;
-       sha_params.buscorerev = wlc_hw->sih->buscorerev;
 
        /* alloc and save pointer to shared phy state area */
        wlc_hw->phy_sh = wlc_phy_shared_attach(&sha_params);
@@ -4615,9 +4603,9 @@ static int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device,
                wlc_hw->band->bandtype = j ? BRCM_BAND_5G : BRCM_BAND_2G;
                wlc->band->bandunit = j;
                wlc->band->bandtype = j ? BRCM_BAND_5G : BRCM_BAND_2G;
-               wlc->core->coreidx = ai_coreidx(wlc_hw->sih);
+               wlc->core->coreidx = core->core_index;
 
-               wlc_hw->machwcap = R_REG(&regs->machwcap);
+               wlc_hw->machwcap = bcma_read32(core, D11REGOFFS(machwcap));
                wlc_hw->machwcap_backup = wlc_hw->machwcap;
 
                /* init tx fifo size */
@@ -4626,7 +4614,7 @@ static int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device,
 
                /* Get a phy for this band */
                wlc_hw->band->pi =
-                       wlc_phy_attach(wlc_hw->phy_sh, regs,
+                       wlc_phy_attach(wlc_hw->phy_sh, core,
                                       wlc_hw->band->bandtype,
                                       wlc->wiphy);
                if (wlc_hw->band->pi == NULL) {
@@ -4700,10 +4688,6 @@ static int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device,
        /* Match driver "down" state */
        ai_pci_down(wlc_hw->sih);
 
-       /* register sb interrupt callback functions */
-       ai_register_intr_callback(wlc_hw->sih, (void *)brcms_c_wlintrsoff,
-                                 (void *)brcms_c_wlintrsrestore, NULL, wlc);
-
        /* turn off pll and xtal to match driver "down" state */
        brcms_b_xtal(wlc_hw, OFF);
 
@@ -4734,10 +4718,9 @@ static int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device,
                goto fail;
        }
 
-       BCMMSG(wlc->wiphy,
-                "deviceid 0x%x nbands %d board 0x%x macaddr: %s\n",
-                wlc_hw->deviceid, wlc_hw->_nbands,
-                wlc_hw->sih->boardtype, macaddr);
+       BCMMSG(wlc->wiphy, "deviceid 0x%x nbands %d board 0x%x macaddr: %s\n",
+              wlc_hw->deviceid, wlc_hw->_nbands, ai_get_boardtype(wlc_hw->sih),
+              macaddr);
 
        return err;
 
@@ -4975,7 +4958,6 @@ static int brcms_b_detach(struct brcms_c_info *wlc)
                 * and per-port interrupt object may has been freed. this must
                 * be done before sb core switch
                 */
-               ai_deregister_intr_callback(wlc_hw->sih);
                ai_pci_sleep(wlc_hw->sih);
        }
 
@@ -5070,13 +5052,11 @@ static void brcms_b_hw_up(struct brcms_hardware *wlc_hw)
        ai_pci_fixcfg(wlc_hw->sih);
 
        /*
+        * TODO: test suspend/resume
+        *
         * AI chip doesn't restore bar0win2 on
         * hibernation/resume, need sw fixup
         */
-       if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) ||
-           (wlc_hw->sih->chip == BCM43225_CHIP_ID))
-               wlc_hw->regs = (struct d11regs __iomem *)
-                               ai_setcore(wlc_hw->sih, D11_CORE_ID, 0);
 
        /*
         * Inform phy that a POR reset has occurred so
@@ -5088,7 +5068,7 @@ static void brcms_b_hw_up(struct brcms_hardware *wlc_hw)
        wlc_hw->wlc->pub->hw_up = true;
 
        if ((wlc_hw->boardflags & BFL_FEM)
-           && (wlc_hw->sih->chip == BCM4313_CHIP_ID)) {
+           && (ai_get_chip_id(wlc_hw->sih) == BCM4313_CHIP_ID)) {
                if (!
                    (wlc_hw->boardrev >= 0x1250
                     && (wlc_hw->boardflags & BFL_FEM_BT)))
@@ -5183,7 +5163,7 @@ int brcms_c_up(struct brcms_c_info *wlc)
        }
 
        if ((wlc->pub->boardflags & BFL_FEM)
-           && (wlc->pub->sih->chip == BCM4313_CHIP_ID)) {
+           && (ai_get_chip_id(wlc->hw->sih) == BCM4313_CHIP_ID)) {
                if (wlc->pub->boardrev >= 0x1250
                    && (wlc->pub->boardflags & BFL_FEM_BT))
                        brcms_b_mhf(wlc->hw, MHF5, MHF5_4313_GPIOCTRL,
@@ -5320,9 +5300,9 @@ static int brcms_b_down_finish(struct brcms_hardware *wlc_hw)
        } else {
 
                /* Reset and disable the core */
-               if (ai_iscoreup(wlc_hw->sih)) {
-                       if (R_REG(&wlc_hw->regs->maccontrol) &
-                           MCTL_EN_MAC)
+               if (bcma_core_is_enabled(wlc_hw->d11core)) {
+                       if (bcma_read32(wlc_hw->d11core,
+                                       D11REGOFFS(maccontrol)) & MCTL_EN_MAC)
                                brcms_c_suspend_mac_and_wait(wlc_hw->wlc);
                        callbacks += brcms_reset(wlc_hw->wlc->wl);
                        brcms_c_coredisable(wlc_hw);
@@ -7479,11 +7459,11 @@ static void
 brcms_b_read_tsf(struct brcms_hardware *wlc_hw, u32 *tsf_l_ptr,
                  u32 *tsf_h_ptr)
 {
-       struct d11regs __iomem *regs = wlc_hw->regs;
+       struct bcma_device *core = wlc_hw->d11core;
 
        /* read the tsf timer low, then high to get an atomic read */
-       *tsf_l_ptr = R_REG(&regs->tsf_timerlow);
-       *tsf_h_ptr = R_REG(&regs->tsf_timerhigh);
+       *tsf_l_ptr = bcma_read32(core, D11REGOFFS(tsf_timerlow));
+       *tsf_h_ptr = bcma_read32(core, D11REGOFFS(tsf_timerhigh));
 }
 
 /*
@@ -8156,7 +8136,7 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
 {
        u32 macintstatus;
        struct brcms_hardware *wlc_hw = wlc->hw;
-       struct d11regs __iomem *regs = wlc_hw->regs;
+       struct bcma_device *core = wlc_hw->d11core;
        struct wiphy *wiphy = wlc->wiphy;
 
        if (brcms_deviceremoved(wlc)) {
@@ -8192,7 +8172,7 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
        /* ATIM window end */
        if (macintstatus & MI_ATIMWINEND) {
                BCMMSG(wlc->wiphy, "end of ATIM window\n");
-               OR_REG(&regs->maccommand, wlc->qvalid);
+               bcma_set32(core, D11REGOFFS(maccommand), wlc->qvalid);
                wlc->qvalid = 0;
        }
 
@@ -8210,17 +8190,17 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
 
        if (macintstatus & MI_GP0) {
                wiphy_err(wiphy, "wl%d: PSM microcode watchdog fired at %d "
-                       "(seconds). Resetting.\n", wlc_hw->unit, wlc_hw->now);
+                         "(seconds). Resetting.\n", wlc_hw->unit, wlc_hw->now);
 
                printk_once("%s : PSM Watchdog, chipid 0x%x, chiprev 0x%x\n",
-                                       __func__, wlc_hw->sih->chip,
-                                       wlc_hw->sih->chiprev);
+                           __func__, ai_get_chip_id(wlc_hw->sih),
+                           ai_get_chiprev(wlc_hw->sih));
                brcms_fatal_error(wlc_hw->wlc->wl);
        }
 
        /* gptimer timeout */
        if (macintstatus & MI_TO)
-               W_REG(&regs->gptimer, 0);
+               bcma_write32(core, D11REGOFFS(gptimer), 0);
 
        if (macintstatus & MI_RFDISABLE) {
                BCMMSG(wlc->wiphy, "wl%d: BMAC Detected a change on the"
@@ -8242,13 +8222,11 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
 
 void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx)
 {
-       struct d11regs __iomem *regs;
+       struct bcma_device *core = wlc->hw->d11core;
        u16 chanspec;
 
        BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
 
-       regs = wlc->regs;
-
        /*
         * This will happen if a big-hammer was executed. In
         * that case, we want to go back to the channel that
@@ -8278,8 +8256,8 @@ void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx)
                 * update since init path would reset
                 * to default value
                 */
-               W_REG(&regs->tsf_cfprep,
-                     (bi << CFPREP_CBI_SHIFT));
+               bcma_write32(core, D11REGOFFS(tsf_cfprep),
+                            bi << CFPREP_CBI_SHIFT);
 
                /* Update maccontrol PM related bits */
                brcms_c_set_ps_ctrl(wlc);
@@ -8309,7 +8287,7 @@ void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx)
        brcms_c_bsinit(wlc);
 
        /* Enable EDCF mode (while the MAC is suspended) */
-       OR_REG(&regs->ifs_ctl, IFS_USEEDCF);
+       bcma_set16(core, D11REGOFFS(ifs_ctl), IFS_USEEDCF);
        brcms_c_edcf_setparams(wlc, false);
 
        /* Init precedence maps for empty FIFOs */
@@ -8333,7 +8311,7 @@ void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx)
        brcms_c_txflowcontrol_reset(wlc);
 
        /* enable the RF Disable Delay timer */
-       W_REG(&wlc->regs->rfdisabledly, RFDISABLE_DEFAULT);
+       bcma_write32(core, D11REGOFFS(rfdisabledly), RFDISABLE_DEFAULT);
 
        /*
         * Initialize WME parameters; if they haven't been set by some other
@@ -8353,9 +8331,8 @@ void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx)
  * The common driver entry routine. Error codes should be unique
  */
 struct brcms_c_info *
-brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device, uint unit,
-              bool piomode, void __iomem *regsva, struct pci_dev *btparam,
-              uint *perr)
+brcms_c_attach(struct brcms_info *wl, struct bcma_device *core, uint unit,
+              bool piomode, uint *perr)
 {
        struct brcms_c_info *wlc;
        uint err = 0;
@@ -8363,7 +8340,7 @@ brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device, uint unit,
        struct brcms_pub *pub;
 
        /* allocate struct brcms_c_info state and its substructures */
-       wlc = (struct brcms_c_info *) brcms_c_attach_malloc(unit, &err, device);
+       wlc = (struct brcms_c_info *) brcms_c_attach_malloc(unit, &err, 0);
        if (wlc == NULL)
                goto fail;
        wlc->wiphy = wl->wiphy;
@@ -8390,8 +8367,7 @@ brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device, uint unit,
         * low level attach steps(all hw accesses go
         * inside, no more in rest of the attach)
         */
-       err = brcms_b_attach(wlc, vendor, device, unit, piomode, regsva,
-                            btparam);
+       err = brcms_b_attach(wlc, core, unit, piomode);
        if (err)
                goto fail;
 
index e2de97d9363565a8da848b3186e4246f08f3b6a6..adb136ec1f04b0db413bac1f02f915c0222db36a 100644 (file)
@@ -334,7 +334,7 @@ struct brcms_hardware {
        u32 machwcap_backup;    /* backup of machwcap */
 
        struct si_pub *sih;     /* SI handle (cookie for siutils calls) */
-       struct d11regs __iomem *regs;   /* pointer to device registers */
+       struct bcma_device *d11core;    /* pointer to 802.11 core */
        struct phy_shim_info *physhim; /* phy shim layer handler */
        struct shared_phy *phy_sh;      /* pointer to shared phy state */
        struct brcms_hw_band *band;/* pointer to active per-band state */
@@ -400,7 +400,6 @@ struct brcms_txq_info {
  *
  * pub: pointer to driver public state.
  * wl: pointer to specific private state.
- * regs: pointer to device registers.
  * hw: HW related state.
  * clkreq_override: setting for clkreq for PCIE : Auto, 0, 1.
  * fastpwrup_dly: time in us needed to bring up d11 fast clock.
@@ -477,7 +476,6 @@ struct brcms_txq_info {
 struct brcms_c_info {
        struct brcms_pub *pub;
        struct brcms_info *wl;
-       struct d11regs __iomem *regs;
        struct brcms_hardware *hw;
 
        /* clock */
index 0bcb2679204677cf55532fc4704c7d8484d9c2ef..7fad6dc19258f21fb465ea3fb73a700ff4d54cf6 100644 (file)
 #define SRSH_PI_MASK   0xf000  /* bit 15:12 */
 #define SRSH_PI_SHIFT  12      /* bit 15:12 */
 
+#define PCIREGOFFS(field)      offsetof(struct sbpciregs, field)
+#define PCIEREGOFFS(field)     offsetof(struct sbpcieregs, field)
+
 /* Sonics side: PCI core and host control registers */
 struct sbpciregs {
        u32 control;            /* PCI control */
@@ -205,11 +208,7 @@ struct sbpcieregs {
 };
 
 struct pcicore_info {
-       union {
-               struct sbpcieregs __iomem *pcieregs;
-               struct sbpciregs __iomem *pciregs;
-       } regs;                 /* Memory mapped register to the core */
-
+       struct bcma_device *core;
        struct si_pub *sih;     /* System interconnect handle */
        struct pci_dev *dev;
        u8 pciecap_lcreg_offset;/* PCIE capability LCreg offset
@@ -224,9 +223,9 @@ struct pcicore_info {
 };
 
 #define PCIE_ASPM(sih)                                                 \
-       (((sih)->buscoretype == PCIE_CORE_ID) &&                        \
-        (((sih)->buscorerev >= 3) &&                                   \
-         ((sih)->buscorerev <= 5)))
+       ((ai_get_buscoretype(sih) == PCIE_CORE_ID) &&                   \
+        ((ai_get_buscorerev(sih) >= 3) &&                              \
+         (ai_get_buscorerev(sih) <= 5)))
 
 
 /* delay needed between the mdio control/ mdiodata register data access */
@@ -238,8 +237,7 @@ static void pr28829_delay(void)
 /* Initialize the PCI core.
  * It's caller's responsibility to make sure that this is done only once
  */
-struct pcicore_info *pcicore_init(struct si_pub *sih, struct pci_dev *pdev,
-                                 void __iomem *regs)
+struct pcicore_info *pcicore_init(struct si_pub *sih, struct bcma_device *core)
 {
        struct pcicore_info *pi;
 
@@ -249,17 +247,15 @@ struct pcicore_info *pcicore_init(struct si_pub *sih, struct pci_dev *pdev,
                return NULL;
 
        pi->sih = sih;
-       pi->dev = pdev;
+       pi->dev = core->bus->host_pci;
+       pi->core = core;
 
-       if (sih->buscoretype == PCIE_CORE_ID) {
+       if (core->id.id == PCIE_CORE_ID) {
                u8 cap_ptr;
-               pi->regs.pcieregs = regs;
                cap_ptr = pcicore_find_pci_capability(pi->dev, PCI_CAP_ID_EXP,
                                                      NULL, NULL);
                pi->pciecap_lcreg_offset = cap_ptr + PCIE_CAP_LINKCTRL_OFFSET;
-       } else
-               pi->regs.pciregs = regs;
-
+       }
        return pi;
 }
 
@@ -334,37 +330,37 @@ end:
 
 /* ***** Register Access API */
 static uint
-pcie_readreg(struct sbpcieregs __iomem *pcieregs, uint addrtype, uint offset)
+pcie_readreg(struct bcma_device *core, uint addrtype, uint offset)
 {
        uint retval = 0xFFFFFFFF;
 
        switch (addrtype) {
        case PCIE_CONFIGREGS:
-               W_REG(&pcieregs->configaddr, offset);
-               (void)R_REG((&pcieregs->configaddr));
-               retval = R_REG(&pcieregs->configdata);
+               bcma_write32(core, PCIEREGOFFS(configaddr), offset);
+               (void)bcma_read32(core, PCIEREGOFFS(configaddr));
+               retval = bcma_read32(core, PCIEREGOFFS(configdata));
                break;
        case PCIE_PCIEREGS:
-               W_REG(&pcieregs->pcieindaddr, offset);
-               (void)R_REG(&pcieregs->pcieindaddr);
-               retval = R_REG(&pcieregs->pcieinddata);
+               bcma_write32(core, PCIEREGOFFS(pcieindaddr), offset);
+               (void)bcma_read32(core, PCIEREGOFFS(pcieindaddr));
+               retval = bcma_read32(core, PCIEREGOFFS(pcieinddata));
                break;
        }
 
        return retval;
 }
 
-static uint pcie_writereg(struct sbpcieregs __iomem *pcieregs, uint addrtype,
+static uint pcie_writereg(struct bcma_device *core, uint addrtype,
                          uint offset, uint val)
 {
        switch (addrtype) {
        case PCIE_CONFIGREGS:
-               W_REG((&pcieregs->configaddr), offset);
-               W_REG((&pcieregs->configdata), val);
+               bcma_write32(core, PCIEREGOFFS(configaddr), offset);
+               bcma_write32(core, PCIEREGOFFS(configdata), val);
                break;
        case PCIE_PCIEREGS:
-               W_REG((&pcieregs->pcieindaddr), offset);
-               W_REG((&pcieregs->pcieinddata), val);
+               bcma_write32(core, PCIEREGOFFS(pcieindaddr), offset);
+               bcma_write32(core, PCIEREGOFFS(pcieinddata), val);
                break;
        default:
                break;
@@ -374,7 +370,6 @@ static uint pcie_writereg(struct sbpcieregs __iomem *pcieregs, uint addrtype,
 
 static bool pcie_mdiosetblock(struct pcicore_info *pi, uint blk)
 {
-       struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs;
        uint mdiodata, i = 0;
        uint pcie_serdes_spinwait = 200;
 
@@ -382,12 +377,13 @@ static bool pcie_mdiosetblock(struct pcicore_info *pi, uint blk)
                    (MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) |
                    (MDIODATA_BLK_ADDR << MDIODATA_REGADDR_SHF) |
                    (blk << 4));
-       W_REG(&pcieregs->mdiodata, mdiodata);
+       bcma_write32(pi->core, PCIEREGOFFS(mdiodata), mdiodata);
 
        pr28829_delay();
        /* retry till the transaction is complete */
        while (i < pcie_serdes_spinwait) {
-               if (R_REG(&pcieregs->mdiocontrol) & MDIOCTL_ACCESS_DONE)
+               if (bcma_read32(pi->core, PCIEREGOFFS(mdiocontrol)) &
+                   MDIOCTL_ACCESS_DONE)
                        break;
 
                udelay(1000);
@@ -404,15 +400,15 @@ static int
 pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr, bool write,
            uint *val)
 {
-       struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs;
        uint mdiodata;
        uint i = 0;
        uint pcie_serdes_spinwait = 10;
 
        /* enable mdio access to SERDES */
-       W_REG(&pcieregs->mdiocontrol, MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL);
+       bcma_write32(pi->core, PCIEREGOFFS(mdiocontrol),
+                    MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL);
 
-       if (pi->sih->buscorerev >= 10) {
+       if (ai_get_buscorerev(pi->sih) >= 10) {
                /* new serdes is slower in rw,
                 * using two layers of reg address mapping
                 */
@@ -432,20 +428,22 @@ pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr, bool write,
                mdiodata |= (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA |
                             *val);
 
-       W_REG(&pcieregs->mdiodata, mdiodata);
+       bcma_write32(pi->core, PCIEREGOFFS(mdiodata), mdiodata);
 
        pr28829_delay();
 
        /* retry till the transaction is complete */
        while (i < pcie_serdes_spinwait) {
-               if (R_REG(&pcieregs->mdiocontrol) & MDIOCTL_ACCESS_DONE) {
+               if (bcma_read32(pi->core, PCIEREGOFFS(mdiocontrol)) &
+                   MDIOCTL_ACCESS_DONE) {
                        if (!write) {
                                pr28829_delay();
-                               *val = (R_REG(&pcieregs->mdiodata) &
+                               *val = (bcma_read32(pi->core,
+                                                   PCIEREGOFFS(mdiodata)) &
                                        MDIODATA_MASK);
                        }
                        /* Disable mdio access to SERDES */
-                       W_REG(&pcieregs->mdiocontrol, 0);
+                       bcma_write32(pi->core, PCIEREGOFFS(mdiocontrol), 0);
                        return 0;
                }
                udelay(1000);
@@ -453,7 +451,7 @@ pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr, bool write,
        }
 
        /* Timed out. Disable mdio access to SERDES. */
-       W_REG(&pcieregs->mdiocontrol, 0);
+       bcma_write32(pi->core, PCIEREGOFFS(mdiocontrol), 0);
        return 1;
 }
 
@@ -502,18 +500,18 @@ static void pcie_extendL1timer(struct pcicore_info *pi, bool extend)
 {
        u32 w;
        struct si_pub *sih = pi->sih;
-       struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs;
 
-       if (sih->buscoretype != PCIE_CORE_ID || sih->buscorerev < 7)
+       if (ai_get_buscoretype(sih) != PCIE_CORE_ID ||
+           ai_get_buscorerev(sih) < 7)
                return;
 
-       w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG);
+       w = pcie_readreg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG);
        if (extend)
                w |= PCIE_ASPMTIMER_EXTEND;
        else
                w &= ~PCIE_ASPMTIMER_EXTEND;
-       pcie_writereg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG, w);
-       w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG);
+       pcie_writereg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG, w);
+       w = pcie_readreg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG);
 }
 
 /* centralized clkreq control policy */
@@ -527,25 +525,27 @@ static void pcie_clkreq_upd(struct pcicore_info *pi, uint state)
                        pcie_clkreq(pi, 1, 0);
                break;
        case SI_PCIDOWN:
-               if (sih->buscorerev == 6) {     /* turn on serdes PLL down */
-                       ai_corereg(sih, SI_CC_IDX,
-                                  offsetof(struct chipcregs, chipcontrol_addr),
-                                  ~0, 0);
-                       ai_corereg(sih, SI_CC_IDX,
-                                  offsetof(struct chipcregs, chipcontrol_data),
-                                  ~0x40, 0);
+               /* turn on serdes PLL down */
+               if (ai_get_buscorerev(sih) == 6) {
+                       ai_cc_reg(sih,
+                                 offsetof(struct chipcregs, chipcontrol_addr),
+                                 ~0, 0);
+                       ai_cc_reg(sih,
+                                 offsetof(struct chipcregs, chipcontrol_data),
+                                 ~0x40, 0);
                } else if (pi->pcie_pr42767) {
                        pcie_clkreq(pi, 1, 1);
                }
                break;
        case SI_PCIUP:
-               if (sih->buscorerev == 6) {     /* turn off serdes PLL down */
-                       ai_corereg(sih, SI_CC_IDX,
-                                  offsetof(struct chipcregs, chipcontrol_addr),
-                                  ~0, 0);
-                       ai_corereg(sih, SI_CC_IDX,
-                                  offsetof(struct chipcregs, chipcontrol_data),
-                                  ~0x40, 0x40);
+               /* turn off serdes PLL down */
+               if (ai_get_buscorerev(sih) == 6) {
+                       ai_cc_reg(sih,
+                                 offsetof(struct chipcregs, chipcontrol_addr),
+                                 ~0, 0);
+                       ai_cc_reg(sih,
+                                 offsetof(struct chipcregs, chipcontrol_data),
+                                 ~0x40, 0x40);
                } else if (PCIE_ASPM(sih)) {    /* disable clkreq */
                        pcie_clkreq(pi, 1, 0);
                }
@@ -562,7 +562,7 @@ static void pcie_war_polarity(struct pcicore_info *pi)
        if (pi->pcie_polarity != 0)
                return;
 
-       w = pcie_readreg(pi->regs.pcieregs, PCIE_PCIEREGS, PCIE_PLP_STATUSREG);
+       w = pcie_readreg(pi->core, PCIE_PCIEREGS, PCIE_PLP_STATUSREG);
 
        /* Detect the current polarity at attach and force that polarity and
         * disable changing the polarity
@@ -581,18 +581,15 @@ static void pcie_war_polarity(struct pcicore_info *pi)
  */
 static void pcie_war_aspm_clkreq(struct pcicore_info *pi)
 {
-       struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs;
        struct si_pub *sih = pi->sih;
        u16 val16;
-       u16 __iomem *reg16;
        u32 w;
 
        if (!PCIE_ASPM(sih))
                return;
 
        /* bypass this on QT or VSIM */
-       reg16 = &pcieregs->sprom[SRSH_ASPM_OFFSET];
-       val16 = R_REG(reg16);
+       val16 = bcma_read16(pi->core, PCIEREGOFFS(sprom[SRSH_ASPM_OFFSET]));
 
        val16 &= ~SRSH_ASPM_ENB;
        if (pi->pcie_war_aspm_ovr == PCIE_ASPM_ENAB)
@@ -602,15 +599,15 @@ static void pcie_war_aspm_clkreq(struct pcicore_info *pi)
        else if (pi->pcie_war_aspm_ovr == PCIE_ASPM_L0s_ENAB)
                val16 |= SRSH_ASPM_L0s_ENB;
 
-       W_REG(reg16, val16);
+       bcma_write16(pi->core, PCIEREGOFFS(sprom[SRSH_ASPM_OFFSET]), val16);
 
        pci_read_config_dword(pi->dev, pi->pciecap_lcreg_offset, &w);
        w &= ~PCIE_ASPM_ENAB;
        w |= pi->pcie_war_aspm_ovr;
        pci_write_config_dword(pi->dev, pi->pciecap_lcreg_offset, w);
 
-       reg16 = &pcieregs->sprom[SRSH_CLKREQ_OFFSET_REV5];
-       val16 = R_REG(reg16);
+       val16 = bcma_read16(pi->core,
+                           PCIEREGOFFS(sprom[SRSH_CLKREQ_OFFSET_REV5]));
 
        if (pi->pcie_war_aspm_ovr != PCIE_ASPM_DISAB) {
                val16 |= SRSH_CLKREQ_ENB;
@@ -618,7 +615,8 @@ static void pcie_war_aspm_clkreq(struct pcicore_info *pi)
        } else
                val16 &= ~SRSH_CLKREQ_ENB;
 
-       W_REG(reg16, val16);
+       bcma_write16(pi->core, PCIEREGOFFS(sprom[SRSH_CLKREQ_OFFSET_REV5]),
+                    val16);
 }
 
 /* Apply the polarity determined at the start */
@@ -642,16 +640,15 @@ static void pcie_war_serdes(struct pcicore_info *pi)
 /* Needs to happen when coming out of 'standby'/'hibernate' */
 static void pcie_misc_config_fixup(struct pcicore_info *pi)
 {
-       struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs;
        u16 val16;
-       u16 __iomem *reg16;
 
-       reg16 = &pcieregs->sprom[SRSH_PCIE_MISC_CONFIG];
-       val16 = R_REG(reg16);
+       val16 = bcma_read16(pi->core,
+                           PCIEREGOFFS(sprom[SRSH_PCIE_MISC_CONFIG]));
 
        if ((val16 & SRSH_L23READY_EXIT_NOPERST) == 0) {
                val16 |= SRSH_L23READY_EXIT_NOPERST;
-               W_REG(reg16, val16);
+               bcma_write16(pi->core,
+                            PCIEREGOFFS(sprom[SRSH_PCIE_MISC_CONFIG]), val16);
        }
 }
 
@@ -659,62 +656,57 @@ static void pcie_misc_config_fixup(struct pcicore_info *pi)
 /* Needs to happen when coming out of 'standby'/'hibernate' */
 static void pcie_war_noplldown(struct pcicore_info *pi)
 {
-       struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs;
-       u16 __iomem *reg16;
-
        /* turn off serdes PLL down */
-       ai_corereg(pi->sih, SI_CC_IDX, offsetof(struct chipcregs, chipcontrol),
-                  CHIPCTRL_4321_PLL_DOWN, CHIPCTRL_4321_PLL_DOWN);
+       ai_cc_reg(pi->sih, offsetof(struct chipcregs, chipcontrol),
+                 CHIPCTRL_4321_PLL_DOWN, CHIPCTRL_4321_PLL_DOWN);
 
        /* clear srom shadow backdoor */
-       reg16 = &pcieregs->sprom[SRSH_BD_OFFSET];
-       W_REG(reg16, 0);
+       bcma_write16(pi->core, PCIEREGOFFS(sprom[SRSH_BD_OFFSET]), 0);
 }
 
 /* Needs to happen when coming out of 'standby'/'hibernate' */
 static void pcie_war_pci_setup(struct pcicore_info *pi)
 {
        struct si_pub *sih = pi->sih;
-       struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs;
        u32 w;
 
-       if (sih->buscorerev == 0 || sih->buscorerev == 1) {
-               w = pcie_readreg(pcieregs, PCIE_PCIEREGS,
+       if (ai_get_buscorerev(sih) == 0 || ai_get_buscorerev(sih) == 1) {
+               w = pcie_readreg(pi->core, PCIE_PCIEREGS,
                                 PCIE_TLP_WORKAROUNDSREG);
                w |= 0x8;
-               pcie_writereg(pcieregs, PCIE_PCIEREGS,
+               pcie_writereg(pi->core, PCIE_PCIEREGS,
                              PCIE_TLP_WORKAROUNDSREG, w);
        }
 
-       if (sih->buscorerev == 1) {
-               w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_LCREG);
+       if (ai_get_buscorerev(sih) == 1) {
+               w = pcie_readreg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_LCREG);
                w |= 0x40;
-               pcie_writereg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_LCREG, w);
+               pcie_writereg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_LCREG, w);
        }
 
-       if (sih->buscorerev == 0) {
+       if (ai_get_buscorerev(sih) == 0) {
                pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_TIMER1, 0x8128);
                pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDR, 0x0100);
                pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDRBW, 0x1466);
        } else if (PCIE_ASPM(sih)) {
                /* Change the L1 threshold for better performance */
-               w = pcie_readreg(pcieregs, PCIE_PCIEREGS,
+               w = pcie_readreg(pi->core, PCIE_PCIEREGS,
                                 PCIE_DLLP_PMTHRESHREG);
                w &= ~PCIE_L1THRESHOLDTIME_MASK;
                w |= PCIE_L1THRESHOLD_WARVAL << PCIE_L1THRESHOLDTIME_SHIFT;
-               pcie_writereg(pcieregs, PCIE_PCIEREGS,
+               pcie_writereg(pi->core, PCIE_PCIEREGS,
                              PCIE_DLLP_PMTHRESHREG, w);
 
                pcie_war_serdes(pi);
 
                pcie_war_aspm_clkreq(pi);
-       } else if (pi->sih->buscorerev == 7)
+       } else if (ai_get_buscorerev(pi->sih) == 7)
                pcie_war_noplldown(pi);
 
        /* Note that the fix is actually in the SROM,
         * that's why this is open-ended
         */
-       if (pi->sih->buscorerev >= 6)
+       if (ai_get_buscorerev(pi->sih) >= 6)
                pcie_misc_config_fixup(pi);
 }
 
@@ -745,7 +737,7 @@ void pcicore_attach(struct pcicore_info *pi, int state)
 
 void pcicore_hwup(struct pcicore_info *pi)
 {
-       if (!pi || pi->sih->buscoretype != PCIE_CORE_ID)
+       if (!pi || ai_get_buscoretype(pi->sih) != PCIE_CORE_ID)
                return;
 
        pcie_war_pci_setup(pi);
@@ -753,7 +745,7 @@ void pcicore_hwup(struct pcicore_info *pi)
 
 void pcicore_up(struct pcicore_info *pi, int state)
 {
-       if (!pi || pi->sih->buscoretype != PCIE_CORE_ID)
+       if (!pi || ai_get_buscoretype(pi->sih) != PCIE_CORE_ID)
                return;
 
        /* Restore L1 timer for better performance */
@@ -781,7 +773,7 @@ void pcicore_sleep(struct pcicore_info *pi)
 
 void pcicore_down(struct pcicore_info *pi, int state)
 {
-       if (!pi || pi->sih->buscoretype != PCIE_CORE_ID)
+       if (!pi || ai_get_buscoretype(pi->sih) != PCIE_CORE_ID)
                return;
 
        pcie_clkreq_upd(pi, state);
@@ -790,46 +782,45 @@ void pcicore_down(struct pcicore_info *pi, int state)
        pcie_extendL1timer(pi, false);
 }
 
-/* precondition: current core is sii->buscoretype */
-static void pcicore_fixcfg(struct pcicore_info *pi, u16 __iomem *reg16)
+void pcicore_fixcfg(struct pcicore_info *pi)
 {
-       struct si_info *sii = (struct si_info *)(pi->sih);
+       struct bcma_device *core = pi->core;
        u16 val16;
-       uint pciidx;
+       uint regoff;
 
-       pciidx = ai_coreidx(&sii->pub);
-       val16 = R_REG(reg16);
-       if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (u16)pciidx) {
-               val16 = (u16)(pciidx << SRSH_PI_SHIFT) |
-                       (val16 & ~SRSH_PI_MASK);
-               W_REG(reg16, val16);
-       }
-}
+       switch (pi->core->id.id) {
+       case BCMA_CORE_PCI:
+               regoff = PCIREGOFFS(sprom[SRSH_PI_OFFSET]);
+               break;
 
-void
-pcicore_fixcfg_pci(struct pcicore_info *pi, struct sbpciregs __iomem *pciregs)
-{
-       pcicore_fixcfg(pi, &pciregs->sprom[SRSH_PI_OFFSET]);
-}
+       case BCMA_CORE_PCIE:
+               regoff = PCIEREGOFFS(sprom[SRSH_PI_OFFSET]);
+               break;
 
-void pcicore_fixcfg_pcie(struct pcicore_info *pi,
-                        struct sbpcieregs __iomem *pcieregs)
-{
-       pcicore_fixcfg(pi, &pcieregs->sprom[SRSH_PI_OFFSET]);
+       default:
+               return;
+       }
+
+       val16 = bcma_read16(pi->core, regoff);
+       if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) !=
+           (u16)core->core_index) {
+               val16 = ((u16)core->core_index << SRSH_PI_SHIFT) |
+                       (val16 & ~SRSH_PI_MASK);
+               bcma_write16(pi->core, regoff, val16);
+       }
 }
 
 /* precondition: current core is pci core */
 void
-pcicore_pci_setup(struct pcicore_info *pi, struct sbpciregs __iomem *pciregs)
+pcicore_pci_setup(struct pcicore_info *pi)
 {
-       u32 w;
-
-       OR_REG(&pciregs->sbtopci2, SBTOPCI_PREF | SBTOPCI_BURST);
-
-       if (((struct si_info *)(pi->sih))->pub.buscorerev >= 11) {
-               OR_REG(&pciregs->sbtopci2, SBTOPCI_RC_READMULTI);
-               w = R_REG(&pciregs->clkrun);
-               W_REG(&pciregs->clkrun, w | PCI_CLKRUN_DSBL);
-               w = R_REG(&pciregs->clkrun);
+       bcma_set32(pi->core, PCIREGOFFS(sbtopci2),
+                  SBTOPCI_PREF | SBTOPCI_BURST);
+
+       if (pi->core->id.rev >= 11) {
+               bcma_set32(pi->core, PCIREGOFFS(sbtopci2),
+                          SBTOPCI_RC_READMULTI);
+               bcma_set32(pi->core, PCIREGOFFS(clkrun), PCI_CLKRUN_DSBL);
+               (void)bcma_read32(pi->core, PCIREGOFFS(clkrun));
        }
 }
index 58aa80dc3329a4c04ee8c29d2e45d780cfeff61d..9fc3ead540a847fd8d5c937a933981ef3abbdd90 100644 (file)
@@ -62,8 +62,7 @@ struct sbpciregs;
 struct sbpcieregs;
 
 extern struct pcicore_info *pcicore_init(struct si_pub *sih,
-                                        struct pci_dev *pdev,
-                                        void __iomem *regs);
+                                        struct bcma_device *core);
 extern void pcicore_deinit(struct pcicore_info *pch);
 extern void pcicore_attach(struct pcicore_info *pch, int state);
 extern void pcicore_hwup(struct pcicore_info *pch);
@@ -72,11 +71,7 @@ extern void pcicore_sleep(struct pcicore_info *pch);
 extern void pcicore_down(struct pcicore_info *pch, int state);
 extern u8 pcicore_find_pci_capability(struct pci_dev *dev, u8 req_cap_id,
                                      unsigned char *buf, u32 *buflen);
-extern void pcicore_fixcfg_pci(struct pcicore_info *pch,
-                              struct sbpciregs __iomem *pciregs);
-extern void pcicore_fixcfg_pcie(struct pcicore_info *pch,
-                               struct sbpcieregs __iomem *pciregs);
-extern void pcicore_pci_setup(struct pcicore_info *pch,
-                             struct sbpciregs __iomem *pciregs);
+extern void pcicore_fixcfg(struct pcicore_info *pch);
+extern void pcicore_pci_setup(struct pcicore_info *pch);
 
 #endif /* _BRCM_NICPCI_H_ */
index edf551561fd8eab55956ec6438a707e51a074fde..f1ca12625860427a74e2011cf7ebb4ad614e1dd1 100644 (file)
@@ -77,7 +77,7 @@ struct otp_fn_s {
 };
 
 struct otpinfo {
-       uint ccrev;             /* chipc revision */
+       struct bcma_device *core; /* chipc core */
        const struct otp_fn_s *fn;      /* OTP functions */
        struct si_pub *sih;             /* Saved sb handle */
 
@@ -133,9 +133,10 @@ struct otpinfo {
 #define OTP_SZ_FU_144          (144/8) /* 144 bits */
 
 static u16
-ipxotp_otpr(struct otpinfo *oi, struct chipcregs __iomem *cc, uint wn)
+ipxotp_otpr(struct otpinfo *oi, uint wn)
 {
-       return R_REG(&cc->sromotp[wn]);
+       return bcma_read16(oi->core,
+                          CHIPCREGOFFS(sromotp[wn]));
 }
 
 /*
@@ -146,7 +147,7 @@ static int ipxotp_max_rgnsz(struct si_pub *sih, int osizew)
 {
        int ret = 0;
 
-       switch (sih->chip) {
+       switch (ai_get_chip_id(sih)) {
        case BCM43224_CHIP_ID:
        case BCM43225_CHIP_ID:
                ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM;
@@ -161,19 +162,21 @@ static int ipxotp_max_rgnsz(struct si_pub *sih, int osizew)
        return ret;
 }
 
-static void _ipxotp_init(struct otpinfo *oi, struct chipcregs __iomem *cc)
+static void _ipxotp_init(struct otpinfo *oi)
 {
        uint k;
        u32 otpp, st;
+       int ccrev = ai_get_ccrev(oi->sih);
+
 
        /*
         * record word offset of General Use Region
         * for various chipcommon revs
         */
-       if (oi->sih->ccrev == 21 || oi->sih->ccrev == 24
-           || oi->sih->ccrev == 27) {
+       if (ccrev == 21 || ccrev == 24
+           || ccrev == 27) {
                oi->otpgu_base = REVA4_OTPGU_BASE;
-       } else if (oi->sih->ccrev == 36) {
+       } else if (ccrev == 36) {
                /*
                 * OTP size greater than equal to 2KB (128 words),
                 * otpgu_base is similar to rev23
@@ -182,7 +185,7 @@ static void _ipxotp_init(struct otpinfo *oi, struct chipcregs __iomem *cc)
                        oi->otpgu_base = REVB8_OTPGU_BASE;
                else
                        oi->otpgu_base = REV36_OTPGU_BASE;
-       } else if (oi->sih->ccrev == 23 || oi->sih->ccrev >= 25) {
+       } else if (ccrev == 23 || ccrev >= 25) {
                oi->otpgu_base = REVB8_OTPGU_BASE;
        }
 
@@ -190,24 +193,21 @@ static void _ipxotp_init(struct otpinfo *oi, struct chipcregs __iomem *cc)
        otpp =
            OTPP_START_BUSY | ((OTPPOC_INIT << OTPP_OC_SHIFT) & OTPP_OC_MASK);
 
-       W_REG(&cc->otpprog, otpp);
-       for (k = 0;
-            ((st = R_REG(&cc->otpprog)) & OTPP_START_BUSY)
-            && (k < OTPP_TRIES); k++)
-               ;
+       bcma_write32(oi->core, CHIPCREGOFFS(otpprog), otpp);
+       st = bcma_read32(oi->core, CHIPCREGOFFS(otpprog));
+       for (k = 0; (st & OTPP_START_BUSY) && (k < OTPP_TRIES); k++)
+               st = bcma_read32(oi->core, CHIPCREGOFFS(otpprog));
        if (k >= OTPP_TRIES)
                return;
 
        /* Read OTP lock bits and subregion programmed indication bits */
-       oi->status = R_REG(&cc->otpstatus);
+       oi->status = bcma_read32(oi->core, CHIPCREGOFFS(otpstatus));
 
-       if ((oi->sih->chip == BCM43224_CHIP_ID)
-           || (oi->sih->chip == BCM43225_CHIP_ID)) {
+       if ((ai_get_chip_id(oi->sih) == BCM43224_CHIP_ID)
+           || (ai_get_chip_id(oi->sih) == BCM43225_CHIP_ID)) {
                u32 p_bits;
-               p_bits =
-                   (ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_P_OFF) &
-                    OTPGU_P_MSK)
-                   >> OTPGU_P_SHIFT;
+               p_bits = (ipxotp_otpr(oi, oi->otpgu_base + OTPGU_P_OFF) &
+                         OTPGU_P_MSK) >> OTPGU_P_SHIFT;
                oi->status |= (p_bits << OTPS_GUP_SHIFT);
        }
 
@@ -220,7 +220,7 @@ static void _ipxotp_init(struct otpinfo *oi, struct chipcregs __iomem *cc)
        oi->hwlim = oi->wsize;
        if (oi->status & OTPS_GUP_HW) {
                oi->hwlim =
-                   ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF) / 16;
+                   ipxotp_otpr(oi, oi->otpgu_base + OTPGU_HSB_OFF) / 16;
                oi->swbase = oi->hwlim;
        } else
                oi->swbase = oi->hwbase;
@@ -230,7 +230,7 @@ static void _ipxotp_init(struct otpinfo *oi, struct chipcregs __iomem *cc)
 
        if (oi->status & OTPS_GUP_SW) {
                oi->swlim =
-                   ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_SFB_OFF) / 16;
+                   ipxotp_otpr(oi, oi->otpgu_base + OTPGU_SFB_OFF) / 16;
                oi->fbase = oi->swlim;
        } else
                oi->fbase = oi->swbase;
@@ -240,11 +240,8 @@ static void _ipxotp_init(struct otpinfo *oi, struct chipcregs __iomem *cc)
 
 static int ipxotp_init(struct si_pub *sih, struct otpinfo *oi)
 {
-       uint idx;
-       struct chipcregs __iomem *cc;
-
        /* Make sure we're running IPX OTP */
-       if (!OTPTYPE_IPX(sih->ccrev))
+       if (!OTPTYPE_IPX(ai_get_ccrev(sih)))
                return -EBADE;
 
        /* Make sure OTP is not disabled */
@@ -252,7 +249,7 @@ static int ipxotp_init(struct si_pub *sih, struct otpinfo *oi)
                return -EBADE;
 
        /* Check for otp size */
-       switch ((sih->cccaps & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT) {
+       switch ((ai_get_cccaps(sih) & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT) {
        case 0:
                /* Nothing there */
                return -EBADE;
@@ -282,21 +279,13 @@ static int ipxotp_init(struct si_pub *sih, struct otpinfo *oi)
        }
 
        /* Retrieve OTP region info */
-       idx = ai_coreidx(sih);
-       cc = ai_setcoreidx(sih, SI_CC_IDX);
-
-       _ipxotp_init(oi, cc);
-
-       ai_setcoreidx(sih, idx);
-
+       _ipxotp_init(oi);
        return 0;
 }
 
 static int
 ipxotp_read_region(struct otpinfo *oi, int region, u16 *data, uint *wlen)
 {
-       uint idx;
-       struct chipcregs __iomem *cc;
        uint base, i, sz;
 
        /* Validate region selection */
@@ -365,14 +354,10 @@ ipxotp_read_region(struct otpinfo *oi, int region, u16 *data, uint *wlen)
                return -EINVAL;
        }
 
-       idx = ai_coreidx(oi->sih);
-       cc = ai_setcoreidx(oi->sih, SI_CC_IDX);
-
        /* Read the data */
        for (i = 0; i < sz; i++)
-               data[i] = ipxotp_otpr(oi, cc, base + i);
+               data[i] = ipxotp_otpr(oi, base + i);
 
-       ai_setcoreidx(oi->sih, idx);
        *wlen = sz;
        return 0;
 }
@@ -384,14 +369,13 @@ static const struct otp_fn_s ipxotp_fn = {
 
 static int otp_init(struct si_pub *sih, struct otpinfo *oi)
 {
-
        int ret;
 
        memset(oi, 0, sizeof(struct otpinfo));
 
-       oi->ccrev = sih->ccrev;
+       oi->core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0);
 
-       if (OTPTYPE_IPX(oi->ccrev))
+       if (OTPTYPE_IPX(ai_get_ccrev(sih)))
                oi->fn = &ipxotp_fn;
 
        if (oi->fn == NULL)
@@ -399,7 +383,7 @@ static int otp_init(struct si_pub *sih, struct otpinfo *oi)
 
        oi->sih = sih;
 
-       ret = (oi->fn->init) (sih, oi);
+       ret = (oi->fn->init)(sih, oi);
 
        return ret;
 }
index 008aab9c777cc5dda99238dc8389d23e88764149..264f8c4c703daf43251c7bd5185df79fd344e8c2 100644 (file)
@@ -149,9 +149,8 @@ void wlc_radioreg_enter(struct brcms_phy_pub *pih)
 void wlc_radioreg_exit(struct brcms_phy_pub *pih)
 {
        struct brcms_phy *pi = (struct brcms_phy *) pih;
-       u16 dummy;
 
-       dummy = R_REG(&pi->regs->phyversion);
+       (void)bcma_read16(pi->d11core, D11REGOFFS(phyversion));
        pi->phy_wreg = 0;
        wlapi_bmac_mctrl(pi->sh->physhim, MCTL_LOCK_RADIO, 0);
 }
@@ -186,11 +185,11 @@ u16 read_radio_reg(struct brcms_phy *pi, u16 addr)
        if ((D11REV_GE(pi->sh->corerev, 24)) ||
            (D11REV_IS(pi->sh->corerev, 22)
             && (pi->pubpi.phy_type != PHY_TYPE_SSN))) {
-               W_REG_FLUSH(&pi->regs->radioregaddr, addr);
-               data = R_REG(&pi->regs->radioregdata);
+               bcma_wflush16(pi->d11core, D11REGOFFS(radioregaddr), addr);
+               data = bcma_read16(pi->d11core, D11REGOFFS(radioregdata));
        } else {
-               W_REG_FLUSH(&pi->regs->phy4waddr, addr);
-               data = R_REG(&pi->regs->phy4wdatalo);
+               bcma_wflush16(pi->d11core, D11REGOFFS(phy4waddr), addr);
+               data = bcma_read16(pi->d11core, D11REGOFFS(phy4wdatalo));
        }
        pi->phy_wreg = 0;
 
@@ -203,15 +202,15 @@ void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val)
            (D11REV_IS(pi->sh->corerev, 22)
             && (pi->pubpi.phy_type != PHY_TYPE_SSN))) {
 
-               W_REG_FLUSH(&pi->regs->radioregaddr, addr);
-               W_REG(&pi->regs->radioregdata, val);
+               bcma_wflush16(pi->d11core, D11REGOFFS(radioregaddr), addr);
+               bcma_write16(pi->d11core, D11REGOFFS(radioregdata), val);
        } else {
-               W_REG_FLUSH(&pi->regs->phy4waddr, addr);
-               W_REG(&pi->regs->phy4wdatalo, val);
+               bcma_wflush16(pi->d11core, D11REGOFFS(phy4waddr), addr);
+               bcma_write16(pi->d11core, D11REGOFFS(phy4wdatalo), val);
        }
 
        if (++pi->phy_wreg >= pi->phy_wreg_limit) {
-               (void)R_REG(&pi->regs->maccontrol);
+               (void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol));
                pi->phy_wreg = 0;
        }
 }
@@ -223,19 +222,20 @@ static u32 read_radio_id(struct brcms_phy *pi)
        if (D11REV_GE(pi->sh->corerev, 24)) {
                u32 b0, b1, b2;
 
-               W_REG_FLUSH(&pi->regs->radioregaddr, 0);
-               b0 = (u32) R_REG(&pi->regs->radioregdata);
-               W_REG_FLUSH(&pi->regs->radioregaddr, 1);
-               b1 = (u32) R_REG(&pi->regs->radioregdata);
-               W_REG_FLUSH(&pi->regs->radioregaddr, 2);
-               b2 = (u32) R_REG(&pi->regs->radioregdata);
+               bcma_wflush16(pi->d11core, D11REGOFFS(radioregaddr), 0);
+               b0 = (u32) bcma_read16(pi->d11core, D11REGOFFS(radioregdata));
+               bcma_wflush16(pi->d11core, D11REGOFFS(radioregaddr), 1);
+               b1 = (u32) bcma_read16(pi->d11core, D11REGOFFS(radioregdata));
+               bcma_wflush16(pi->d11core, D11REGOFFS(radioregaddr), 2);
+               b2 = (u32) bcma_read16(pi->d11core, D11REGOFFS(radioregdata));
 
                id = ((b0 & 0xf) << 28) | (((b2 << 8) | b1) << 12) | ((b0 >> 4)
                                                                      & 0xf);
        } else {
-               W_REG_FLUSH(&pi->regs->phy4waddr, RADIO_IDCODE);
-               id = (u32) R_REG(&pi->regs->phy4wdatalo);
-               id |= (u32) R_REG(&pi->regs->phy4wdatahi) << 16;
+               bcma_wflush16(pi->d11core, D11REGOFFS(phy4waddr), RADIO_IDCODE);
+               id = (u32) bcma_read16(pi->d11core, D11REGOFFS(phy4wdatalo));
+               id |= (u32) bcma_read16(pi->d11core,
+                                       D11REGOFFS(phy4wdatahi)) << 16;
        }
        pi->phy_wreg = 0;
        return id;
@@ -275,75 +275,52 @@ void mod_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val)
 
 void write_phy_channel_reg(struct brcms_phy *pi, uint val)
 {
-       W_REG(&pi->regs->phychannel, val);
+       bcma_write16(pi->d11core, D11REGOFFS(phychannel), val);
 }
 
 u16 read_phy_reg(struct brcms_phy *pi, u16 addr)
 {
-       struct d11regs __iomem *regs;
-
-       regs = pi->regs;
-
-       W_REG_FLUSH(&regs->phyregaddr, addr);
+       bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), addr);
 
        pi->phy_wreg = 0;
-       return R_REG(&regs->phyregdata);
+       return bcma_read16(pi->d11core, D11REGOFFS(phyregdata));
 }
 
 void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val)
 {
-       struct d11regs __iomem *regs;
-
-       regs = pi->regs;
-
 #ifdef CONFIG_BCM47XX
-       W_REG_FLUSH(&regs->phyregaddr, addr);
-       W_REG(&regs->phyregdata, val);
+       bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), addr);
+       bcma_write16(pi->d11core, D11REGOFFS(phyregdata), val);
        if (addr == 0x72)
-               (void)R_REG(&regs->phyregdata);
+               (void)bcma_read16(pi->d11core, D11REGOFFS(phyversion));
 #else
-       W_REG((u32 __iomem *)(&regs->phyregaddr), addr | (val << 16));
+       bcma_write32(pi->d11core, D11REGOFFS(phyregaddr), addr | (val << 16));
        if (++pi->phy_wreg >= pi->phy_wreg_limit) {
                pi->phy_wreg = 0;
-               (void)R_REG(&regs->phyversion);
+               (void)bcma_read16(pi->d11core, D11REGOFFS(phyversion));
        }
 #endif
 }
 
 void and_phy_reg(struct brcms_phy *pi, u16 addr, u16 val)
 {
-       struct d11regs __iomem *regs;
-
-       regs = pi->regs;
-
-       W_REG_FLUSH(&regs->phyregaddr, addr);
-
-       W_REG(&regs->phyregdata, (R_REG(&regs->phyregdata) & val));
+       bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), addr);
+       bcma_mask16(pi->d11core, D11REGOFFS(phyregdata), val);
        pi->phy_wreg = 0;
 }
 
 void or_phy_reg(struct brcms_phy *pi, u16 addr, u16 val)
 {
-       struct d11regs __iomem *regs;
-
-       regs = pi->regs;
-
-       W_REG_FLUSH(&regs->phyregaddr, addr);
-
-       W_REG(&regs->phyregdata, (R_REG(&regs->phyregdata) | val));
+       bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), addr);
+       bcma_set16(pi->d11core, D11REGOFFS(phyregdata), val);
        pi->phy_wreg = 0;
 }
 
 void mod_phy_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val)
 {
-       struct d11regs __iomem *regs;
-
-       regs = pi->regs;
-
-       W_REG_FLUSH(&regs->phyregaddr, addr);
-
-       W_REG(&regs->phyregdata,
-             ((R_REG(&regs->phyregdata) & ~mask) | (val & mask)));
+       val &= mask;
+       bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), addr);
+       bcma_maskset16(pi->d11core, D11REGOFFS(phyregdata), ~mask, val);
        pi->phy_wreg = 0;
 }
 
@@ -404,10 +381,8 @@ struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp)
        sh->sromrev = shp->sromrev;
        sh->boardtype = shp->boardtype;
        sh->boardrev = shp->boardrev;
-       sh->boardvendor = shp->boardvendor;
        sh->boardflags = shp->boardflags;
        sh->boardflags2 = shp->boardflags2;
-       sh->buscorerev = shp->buscorerev;
 
        sh->fast_timer = PHY_SW_TIMER_FAST;
        sh->slow_timer = PHY_SW_TIMER_SLOW;
@@ -450,7 +425,7 @@ static u32 wlc_phy_get_radio_ver(struct brcms_phy *pi)
 }
 
 struct brcms_phy_pub *
-wlc_phy_attach(struct shared_phy *sh, struct d11regs __iomem *regs,
+wlc_phy_attach(struct shared_phy *sh, struct bcma_device *d11core,
               int bandtype, struct wiphy *wiphy)
 {
        struct brcms_phy *pi;
@@ -462,7 +437,7 @@ wlc_phy_attach(struct shared_phy *sh, struct d11regs __iomem *regs,
        if (D11REV_IS(sh->corerev, 4))
                sflags = SISF_2G_PHY | SISF_5G_PHY;
        else
-               sflags = ai_core_sflags(sh->sih, 0, 0);
+               sflags = bcma_aread32(d11core, BCMA_IOST);
 
        if (bandtype == BRCM_BAND_5G) {
                if ((sflags & (SISF_5G_PHY | SISF_DB_PHY)) == 0)
@@ -480,7 +455,7 @@ wlc_phy_attach(struct shared_phy *sh, struct d11regs __iomem *regs,
        if (pi == NULL)
                return NULL;
        pi->wiphy = wiphy;
-       pi->regs = regs;
+       pi->d11core = d11core;
        pi->sh = sh;
        pi->phy_init_por = true;
        pi->phy_wreg_limit = PHY_WREG_LIMIT;
@@ -495,7 +470,7 @@ wlc_phy_attach(struct shared_phy *sh, struct d11regs __iomem *regs,
                pi->pubpi.coreflags = SICF_GMODE;
 
        wlapi_bmac_corereset(pi->sh->physhim, pi->pubpi.coreflags);
-       phyversion = R_REG(&pi->regs->phyversion);
+       phyversion = bcma_read16(pi->d11core, D11REGOFFS(phyversion));
 
        pi->pubpi.phy_type = PHY_TYPE(phyversion);
        pi->pubpi.phy_rev = phyversion & PV_PV_MASK;
@@ -507,8 +482,8 @@ wlc_phy_attach(struct shared_phy *sh, struct d11regs __iomem *regs,
        pi->pubpi.phy_corenum = PHY_CORE_NUM_2;
        pi->pubpi.ana_rev = (phyversion & PV_AV_MASK) >> PV_AV_SHIFT;
 
-       if (!pi->pubpi.phy_type == PHY_TYPE_N &&
-           !pi->pubpi.phy_type == PHY_TYPE_LCN)
+       if (pi->pubpi.phy_type != PHY_TYPE_N &&
+           pi->pubpi.phy_type != PHY_TYPE_LCN)
                goto err;
 
        if (bandtype == BRCM_BAND_5G) {
@@ -779,14 +754,14 @@ void wlc_phy_init(struct brcms_phy_pub *pih, u16 chanspec)
 
        pi->radio_chanspec = chanspec;
 
-       mc = R_REG(&pi->regs->maccontrol);
+       mc = bcma_read32(pi->d11core, D11REGOFFS(maccontrol));
        if (WARN(mc & MCTL_EN_MAC, "HW error MAC running on init"))
                return;
 
        if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN))
                pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC;
 
-       if (WARN(!(ai_core_sflags(pi->sh->sih, 0, 0) & SISF_FCLKA),
+       if (WARN(!(bcma_aread32(pi->d11core, BCMA_IOST) & SISF_FCLKA),
                 "HW error SISF_FCLKA\n"))
                return;
 
@@ -825,8 +800,8 @@ void wlc_phy_cal_init(struct brcms_phy_pub *pih)
        struct brcms_phy *pi = (struct brcms_phy *) pih;
        void (*cal_init)(struct brcms_phy *) = NULL;
 
-       if (WARN((R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) != 0,
-                "HW error: MAC enabled during phy cal\n"))
+       if (WARN((bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
+                 MCTL_EN_MAC) != 0, "HW error: MAC enabled during phy cal\n"))
                return;
 
        if (!pi->initialized) {
@@ -1017,7 +992,7 @@ wlc_phy_init_radio_regs(struct brcms_phy *pi,
 void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on)
 {
 #define DUMMY_PKT_LEN   20
-       struct d11regs __iomem *regs = pi->regs;
+       struct bcma_device *core = pi->d11core;
        int i, count;
        u8 ofdmpkt[DUMMY_PKT_LEN] = {
                0xcc, 0x01, 0x02, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00,
@@ -1033,26 +1008,28 @@ void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on)
        wlapi_bmac_write_template_ram(pi->sh->physhim, 0, DUMMY_PKT_LEN,
                                      dummypkt);
 
-       W_REG(&regs->xmtsel, 0);
+       bcma_write16(core, D11REGOFFS(xmtsel), 0);
 
        if (D11REV_GE(pi->sh->corerev, 11))
-               W_REG(&regs->wepctl, 0x100);
+               bcma_write16(core, D11REGOFFS(wepctl), 0x100);
        else
-               W_REG(&regs->wepctl, 0);
+               bcma_write16(core, D11REGOFFS(wepctl), 0);
 
-       W_REG(&regs->txe_phyctl, (ofdm ? 1 : 0) | PHY_TXC_ANT_0);
+       bcma_write16(core, D11REGOFFS(txe_phyctl),
+                    (ofdm ? 1 : 0) | PHY_TXC_ANT_0);
        if (ISNPHY(pi) || ISLCNPHY(pi))
-               W_REG(&regs->txe_phyctl1, 0x1A02);
+               bcma_write16(core, D11REGOFFS(txe_phyctl1), 0x1A02);
 
-       W_REG(&regs->txe_wm_0, 0);
-       W_REG(&regs->txe_wm_1, 0);
+       bcma_write16(core, D11REGOFFS(txe_wm_0), 0);
+       bcma_write16(core, D11REGOFFS(txe_wm_1), 0);
 
-       W_REG(&regs->xmttplatetxptr, 0);
-       W_REG(&regs->xmttxcnt, DUMMY_PKT_LEN);
+       bcma_write16(core, D11REGOFFS(xmttplatetxptr), 0);
+       bcma_write16(core, D11REGOFFS(xmttxcnt), DUMMY_PKT_LEN);
 
-       W_REG(&regs->xmtsel, ((8 << 8) | (1 << 5) | (1 << 2) | 2));
+       bcma_write16(core, D11REGOFFS(xmtsel),
+                    ((8 << 8) | (1 << 5) | (1 << 2) | 2));
 
-       W_REG(&regs->txe_ctl, 0);
+       bcma_write16(core, D11REGOFFS(txe_ctl), 0);
 
        if (!pa_on) {
                if (ISNPHY(pi))
@@ -1060,27 +1037,28 @@ void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on)
        }
 
        if (ISNPHY(pi) || ISLCNPHY(pi))
-               W_REG(&regs->txe_aux, 0xD0);
+               bcma_write16(core, D11REGOFFS(txe_aux), 0xD0);
        else
-               W_REG(&regs->txe_aux, ((1 << 5) | (1 << 4)));
+               bcma_write16(core, D11REGOFFS(txe_aux), ((1 << 5) | (1 << 4)));
 
-       (void)R_REG(&regs->txe_aux);
+       (void)bcma_read16(core, D11REGOFFS(txe_aux));
 
        i = 0;
        count = ofdm ? 30 : 250;
        while ((i++ < count)
-              && (R_REG(&regs->txe_status) & (1 << 7)))
+              && (bcma_read16(core, D11REGOFFS(txe_status)) & (1 << 7)))
                udelay(10);
 
        i = 0;
 
-       while ((i++ < 10)
-              && ((R_REG(&regs->txe_status) & (1 << 10)) == 0))
+       while ((i++ < 10) &&
+              ((bcma_read16(core, D11REGOFFS(txe_status)) & (1 << 10)) == 0))
                udelay(10);
 
        i = 0;
 
-       while ((i++ < 10) && ((R_REG(&regs->ifsstat) & (1 << 8))))
+       while ((i++ < 10) &&
+              ((bcma_read16(core, D11REGOFFS(ifsstat)) & (1 << 8))))
                udelay(10);
 
        if (!pa_on) {
@@ -1137,7 +1115,7 @@ static bool wlc_phy_cal_txpower_recalc_sw(struct brcms_phy *pi)
 void wlc_phy_switch_radio(struct brcms_phy_pub *pih, bool on)
 {
        struct brcms_phy *pi = (struct brcms_phy *) pih;
-       (void)R_REG(&pi->regs->maccontrol);
+       (void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol));
 
        if (ISNPHY(pi)) {
                wlc_phy_switch_radio_nphy(pi, on);
@@ -1377,7 +1355,7 @@ void wlc_phy_txpower_target_set(struct brcms_phy_pub *ppi,
        memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_SDM],
               &txpwr->mcs_40_mimo[0], BRCMS_NUM_RATES_MCS_2_STREAM);
 
-       if (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)
+       if (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) & MCTL_EN_MAC)
                mac_enabled = true;
 
        if (mac_enabled)
@@ -1407,7 +1385,8 @@ int wlc_phy_txpower_set(struct brcms_phy_pub *ppi, uint qdbm, bool override)
                if (!SCAN_INPROG_PHY(pi)) {
                        bool suspend;
 
-                       suspend = (0 == (R_REG(&pi->regs->maccontrol) &
+                       suspend = (0 == (bcma_read32(pi->d11core,
+                                                    D11REGOFFS(maccontrol)) &
                                         MCTL_EN_MAC));
 
                        if (!suspend)
@@ -1860,18 +1839,17 @@ void wlc_phy_runbist_config(struct brcms_phy_pub *ppi, bool start_end)
 
                if (NREV_IS(pi->pubpi.phy_rev, 3)
                    || NREV_IS(pi->pubpi.phy_rev, 4)) {
-                       W_REG(&pi->regs->phyregaddr, 0xa0);
-                       (void)R_REG(&pi->regs->phyregaddr);
-                       rxc = R_REG(&pi->regs->phyregdata);
-                       W_REG(&pi->regs->phyregdata,
-                             (0x1 << 15) | rxc);
+                       bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr),
+                                     0xa0);
+                       bcma_set16(pi->d11core, D11REGOFFS(phyregdata),
+                                  0x1 << 15);
                }
        } else {
                if (NREV_IS(pi->pubpi.phy_rev, 3)
                    || NREV_IS(pi->pubpi.phy_rev, 4)) {
-                       W_REG(&pi->regs->phyregaddr, 0xa0);
-                       (void)R_REG(&pi->regs->phyregaddr);
-                       W_REG(&pi->regs->phyregdata, rxc);
+                       bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr),
+                                     0xa0);
+                       bcma_write16(pi->d11core, D11REGOFFS(phyregdata), rxc);
                }
 
                wlc_phy_por_inform(ppi);
@@ -1991,7 +1969,9 @@ void wlc_phy_txpower_hw_ctrl_set(struct brcms_phy_pub *ppi, bool hwpwrctrl)
        pi->txpwrctrl = hwpwrctrl;
 
        if (ISNPHY(pi)) {
-               suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+               suspend = (0 == (bcma_read32(pi->d11core,
+                                            D11REGOFFS(maccontrol)) &
+                                MCTL_EN_MAC));
                if (!suspend)
                        wlapi_suspend_mac_and_wait(pi->sh->physhim);
 
@@ -2193,7 +2173,8 @@ void wlc_phy_ant_rxdiv_set(struct brcms_phy_pub *ppi, u8 val)
        if (!pi->sh->clk)
                return;
 
-       suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+       suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
+                        MCTL_EN_MAC));
        if (!suspend)
                wlapi_suspend_mac_and_wait(pi->sh->physhim);
 
@@ -2411,8 +2392,8 @@ wlc_phy_noise_sample_request(struct brcms_phy_pub *pih, u8 reason, u8 ch)
                        wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0);
                        wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0);
 
-                       OR_REG(&pi->regs->maccommand,
-                              MCMD_BG_NOISE);
+                       bcma_set32(pi->d11core, D11REGOFFS(maccommand),
+                                  MCMD_BG_NOISE);
                } else {
                        wlapi_suspend_mac_and_wait(pi->sh->physhim);
                        wlc_lcnphy_deaf_mode(pi, (bool) 0);
@@ -2430,8 +2411,8 @@ wlc_phy_noise_sample_request(struct brcms_phy_pub *pih, u8 reason, u8 ch)
                        wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0);
                        wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0);
 
-                       OR_REG(&pi->regs->maccommand,
-                              MCMD_BG_NOISE);
+                       bcma_set32(pi->d11core, D11REGOFFS(maccommand),
+                                  MCMD_BG_NOISE);
                } else {
                        struct phy_iq_est est[PHY_CORE_MAX];
                        u32 cmplx_pwr[PHY_CORE_MAX];
@@ -2924,29 +2905,29 @@ void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode)
                                mod_phy_reg(pi, 0x44c, (0x1 << 2), (1) << 2);
 
                        }
-                       ai_corereg(pi->sh->sih, SI_CC_IDX,
-                                  offsetof(struct chipcregs, gpiocontrol),
-                                  ~0x0, 0x0);
-                       ai_corereg(pi->sh->sih, SI_CC_IDX,
-                                  offsetof(struct chipcregs, gpioout), 0x40,
-                                  0x40);
-                       ai_corereg(pi->sh->sih, SI_CC_IDX,
-                                  offsetof(struct chipcregs, gpioouten), 0x40,
-                                  0x40);
+                       ai_cc_reg(pi->sh->sih,
+                                 offsetof(struct chipcregs, gpiocontrol),
+                                 ~0x0, 0x0);
+                       ai_cc_reg(pi->sh->sih,
+                                 offsetof(struct chipcregs, gpioout),
+                                 0x40, 0x40);
+                       ai_cc_reg(pi->sh->sih,
+                                 offsetof(struct chipcregs, gpioouten),
+                                 0x40, 0x40);
                } else {
                        mod_phy_reg(pi, 0x44c, (0x1 << 2), (0) << 2);
 
                        mod_phy_reg(pi, 0x44d, (0x1 << 2), (0) << 2);
 
-                       ai_corereg(pi->sh->sih, SI_CC_IDX,
-                                  offsetof(struct chipcregs, gpioout), 0x40,
-                                  0x00);
-                       ai_corereg(pi->sh->sih, SI_CC_IDX,
-                                  offsetof(struct chipcregs, gpioouten), 0x40,
-                                  0x0);
-                       ai_corereg(pi->sh->sih, SI_CC_IDX,
-                                  offsetof(struct chipcregs, gpiocontrol),
-                                  ~0x0, 0x40);
+                       ai_cc_reg(pi->sh->sih,
+                                 offsetof(struct chipcregs, gpioout),
+                                 0x40, 0x00);
+                       ai_cc_reg(pi->sh->sih,
+                                 offsetof(struct chipcregs, gpioouten),
+                                 0x40, 0x0);
+                       ai_cc_reg(pi->sh->sih,
+                                 offsetof(struct chipcregs, gpiocontrol),
+                                 ~0x0, 0x40);
                }
        }
 }
index 96e15163222b37e0e38f16b8ac90ca8cfb1dae11..e34a71e7d24204a0cc6dd0a3cb12fd043ec2636a 100644 (file)
@@ -166,7 +166,6 @@ struct shared_phy_params {
        struct phy_shim_info *physhim;
        uint unit;
        uint corerev;
-       uint buscorerev;
        u16 vid;
        u16 did;
        uint chip;
@@ -175,7 +174,6 @@ struct shared_phy_params {
        uint sromrev;
        uint boardtype;
        uint boardrev;
-       uint boardvendor;
        u32 boardflags;
        u32 boardflags2;
 };
@@ -183,7 +181,7 @@ struct shared_phy_params {
 
 extern struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp);
 extern struct brcms_phy_pub *wlc_phy_attach(struct shared_phy *sh,
-                                           struct d11regs __iomem *regs,
+                                           struct bcma_device *d11core,
                                            int bandtype, struct wiphy *wiphy);
 extern void wlc_phy_detach(struct brcms_phy_pub *ppi);
 
index 5f9478b1c9937be8e0ea94061a390d409b4814a8..af00e2c2b2667fd3bc9fbde56d37adfeaffca935 100644 (file)
@@ -503,10 +503,8 @@ struct shared_phy {
        uint sromrev;
        uint boardtype;
        uint boardrev;
-       uint boardvendor;
        u32 boardflags;
        u32 boardflags2;
-       uint buscorerev;
        uint fast_timer;
        uint slow_timer;
        uint glacial_timer;
@@ -559,7 +557,7 @@ struct brcms_phy {
        } u;
        bool user_txpwr_at_rfport;
 
-       struct d11regs __iomem *regs;
+       struct bcma_device *d11core;
        struct brcms_phy *next;
        struct brcms_phy_pub pubpi;
 
@@ -1090,7 +1088,7 @@ extern void wlc_phy_table_write_nphy(struct brcms_phy *pi, u32, u32, u32,
 
 #define BRCMS_PHY_WAR_PR51571(pi) \
        if (NREV_LT((pi)->pubpi.phy_rev, 3)) \
-               (void)R_REG(&(pi)->regs->maccontrol)
+               (void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol))
 
 extern void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype);
 extern void wlc_phy_aci_reset_nphy(struct brcms_phy *pi);
index a63aa99d981079a8b67b3b12719fbe09857d1f31..efa0142bdad57d37db5a3d32a8d10c212fac1ddd 100644 (file)
@@ -2813,10 +2813,8 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi)
        u16 SAVE_jtag_auxpga = read_radio_reg(pi, RADIO_2064_REG0FF) & 0x10;
        u16 SAVE_iqadc_aux_en = read_radio_reg(pi, RADIO_2064_REG11F) & 4;
        idleTssi = read_phy_reg(pi, 0x4ab);
-       suspend =
-               (0 ==
-                (R_REG(&((struct brcms_phy *) pi)->regs->maccontrol) &
-                 MCTL_EN_MAC));
+       suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
+                        MCTL_EN_MAC));
        if (!suspend)
                wlapi_suspend_mac_and_wait(pi->sh->physhim);
        wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
@@ -2890,7 +2888,8 @@ static void wlc_lcnphy_vbat_temp_sense_setup(struct brcms_phy *pi, u8 mode)
 
        for (i = 0; i < 14; i++)
                values_to_save[i] = read_phy_reg(pi, tempsense_phy_regs[i]);
-       suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+       suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
+                        MCTL_EN_MAC));
        if (!suspend)
                wlapi_suspend_mac_and_wait(pi->sh->physhim);
        save_txpwrCtrlEn = read_radio_reg(pi, 0x4a4);
@@ -3016,8 +3015,8 @@ static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi)
        bool suspend;
        struct brcms_phy *pi = (struct brcms_phy *) ppi;
 
-       suspend =
-               (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+       suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
+                        MCTL_EN_MAC));
        if (!suspend)
                wlapi_suspend_mac_and_wait(pi->sh->physhim);
 
@@ -3535,15 +3534,17 @@ wlc_lcnphy_samp_cap(struct brcms_phy *pi, int clip_detect_algo, u16 thresh,
        timer = 0;
        old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
 
-       curval1 = R_REG(&pi->regs->psm_corectlsts);
+       curval1 = bcma_read16(pi->d11core, D11REGOFFS(psm_corectlsts));
        ptr[130] = 0;
-       W_REG(&pi->regs->psm_corectlsts, ((1 << 6) | curval1));
+       bcma_write16(pi->d11core, D11REGOFFS(psm_corectlsts),
+                    ((1 << 6) | curval1));
 
-       W_REG(&pi->regs->smpl_clct_strptr, 0x7E00);
-       W_REG(&pi->regs->smpl_clct_stpptr, 0x8000);
+       bcma_write16(pi->d11core, D11REGOFFS(smpl_clct_strptr), 0x7E00);
+       bcma_write16(pi->d11core, D11REGOFFS(smpl_clct_stpptr), 0x8000);
        udelay(20);
-       curval2 = R_REG(&pi->regs->psm_phy_hdr_param);
-       W_REG(&pi->regs->psm_phy_hdr_param, curval2 | 0x30);
+       curval2 = bcma_read16(pi->d11core, D11REGOFFS(psm_phy_hdr_param));
+       bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param),
+                    curval2 | 0x30);
 
        write_phy_reg(pi, 0x555, 0x0);
        write_phy_reg(pi, 0x5a6, 0x5);
@@ -3560,19 +3561,19 @@ wlc_lcnphy_samp_cap(struct brcms_phy *pi, int clip_detect_algo, u16 thresh,
 
        sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
        write_phy_reg(pi, 0x6da, (u32) (sslpnCalibClkEnCtrl | 0x2008));
-       stpptr = R_REG(&pi->regs->smpl_clct_stpptr);
-       curptr = R_REG(&pi->regs->smpl_clct_curptr);
+       stpptr = bcma_read16(pi->d11core, D11REGOFFS(smpl_clct_stpptr));
+       curptr = bcma_read16(pi->d11core, D11REGOFFS(smpl_clct_curptr));
        do {
                udelay(10);
-               curptr = R_REG(&pi->regs->smpl_clct_curptr);
+               curptr = bcma_read16(pi->d11core, D11REGOFFS(smpl_clct_curptr));
                timer++;
        } while ((curptr != stpptr) && (timer < 500));
 
-       W_REG(&pi->regs->psm_phy_hdr_param, 0x2);
+       bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param), 0x2);
        strptr = 0x7E00;
-       W_REG(&pi->regs->tplatewrptr, strptr);
+       bcma_write32(pi->d11core, D11REGOFFS(tplatewrptr), strptr);
        while (strptr < 0x8000) {
-               val = R_REG(&pi->regs->tplatewrdata);
+               val = bcma_read32(pi->d11core, D11REGOFFS(tplatewrdata));
                imag = ((val >> 16) & 0x3ff);
                real = ((val) & 0x3ff);
                if (imag > 511)
@@ -3597,8 +3598,8 @@ wlc_lcnphy_samp_cap(struct brcms_phy *pi, int clip_detect_algo, u16 thresh,
        }
 
        write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
-       W_REG(&pi->regs->psm_phy_hdr_param, curval2);
-       W_REG(&pi->regs->psm_corectlsts, curval1);
+       bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param), curval2);
+       bcma_write16(pi->d11core, D11REGOFFS(psm_corectlsts), curval1);
 }
 
 static void
@@ -3968,9 +3969,9 @@ s16 wlc_lcnphy_tempsense_new(struct brcms_phy *pi, bool mode)
        bool suspend = 0;
 
        if (mode == 1) {
-               suspend =
-                       (0 ==
-                        (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+               suspend = (0 == (bcma_read32(pi->d11core,
+                                            D11REGOFFS(maccontrol)) &
+                                MCTL_EN_MAC));
                if (!suspend)
                        wlapi_suspend_mac_and_wait(pi->sh->physhim);
                wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
@@ -4012,9 +4013,9 @@ u16 wlc_lcnphy_tempsense(struct brcms_phy *pi, bool mode)
        struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
 
        if (mode == 1) {
-               suspend =
-                       (0 ==
-                        (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+               suspend = (0 == (bcma_read32(pi->d11core,
+                                            D11REGOFFS(maccontrol)) &
+                                MCTL_EN_MAC));
                if (!suspend)
                        wlapi_suspend_mac_and_wait(pi->sh->physhim);
                wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
@@ -4078,9 +4079,9 @@ s8 wlc_lcnphy_vbatsense(struct brcms_phy *pi, bool mode)
        bool suspend = 0;
 
        if (mode == 1) {
-               suspend =
-                       (0 ==
-                        (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+               suspend = (0 == (bcma_read32(pi->d11core,
+                                            D11REGOFFS(maccontrol)) &
+                                MCTL_EN_MAC));
                if (!suspend)
                        wlapi_suspend_mac_and_wait(pi->sh->physhim);
                wlc_lcnphy_vbat_temp_sense_setup(pi, VBATSENSE);
@@ -4127,8 +4128,8 @@ static void wlc_lcnphy_glacial_timer_based_cal(struct brcms_phy *pi)
        s8 index;
        u16 SAVE_pwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
        struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
-       suspend =
-               (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+       suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
+                        MCTL_EN_MAC));
        if (!suspend)
                wlapi_suspend_mac_and_wait(pi->sh->physhim);
        wlc_lcnphy_deaf_mode(pi, true);
@@ -4166,8 +4167,8 @@ static void wlc_lcnphy_periodic_cal(struct brcms_phy *pi)
        pi_lcn->lcnphy_full_cal_channel = CHSPEC_CHANNEL(pi->radio_chanspec);
        index = pi_lcn->lcnphy_current_index;
 
-       suspend =
-               (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+       suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
+                        MCTL_EN_MAC));
        if (!suspend) {
                wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, 10000);
                wlapi_suspend_mac_and_wait(pi->sh->physhim);
index ec9b56639d544fed3c60d46fc0ed4a021407a96d..a16f1ab292fdb2c87e1d3c5c1a1ada25df897769 100644 (file)
@@ -17802,7 +17802,7 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi)
 
        if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) {
                wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK);
-               (void)R_REG(&pi->regs->maccontrol);
+               (void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol));
                udelay(1);
        }
 
@@ -17953,7 +17953,7 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi)
 
        if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) {
                wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK);
-               (void)R_REG(&pi->regs->maccontrol);
+               (void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol));
                udelay(1);
        }
 
@@ -19447,8 +19447,6 @@ void wlc_phy_init_nphy(struct brcms_phy *pi)
        u8 tx_pwr_ctrl_state;
        bool do_nphy_cal = false;
        uint core;
-       uint origidx, intr_val;
-       struct d11regs __iomem *regs;
        u32 d11_clk_ctl_st;
        bool do_rssi_cal = false;
 
@@ -19462,25 +19460,21 @@ void wlc_phy_init_nphy(struct brcms_phy *pi)
             (pi->sh->chippkg == BCM4718_PKG_ID))) {
                if ((pi->sh->boardflags & BFL_EXTLNA) &&
                    (CHSPEC_IS2G(pi->radio_chanspec)))
-                       ai_corereg(pi->sh->sih, SI_CC_IDX,
-                                  offsetof(struct chipcregs, chipcontrol),
-                                  0x40, 0x40);
+                       ai_cc_reg(pi->sh->sih,
+                                 offsetof(struct chipcregs, chipcontrol),
+                                 0x40, 0x40);
        }
 
        if ((pi->nphy_gband_spurwar2_en) && CHSPEC_IS2G(pi->radio_chanspec) &&
            CHSPEC_IS40(pi->radio_chanspec)) {
 
-               regs = (struct d11regs __iomem *)
-                               ai_switch_core(pi->sh->sih,
-                                              D11_CORE_ID, &origidx,
-                                              &intr_val);
-               d11_clk_ctl_st = R_REG(&regs->clk_ctl_st);
-               AND_REG(&regs->clk_ctl_st,
-                       ~(CCS_FORCEHT | CCS_HTAREQ));
+               d11_clk_ctl_st = bcma_read32(pi->d11core,
+                                            D11REGOFFS(clk_ctl_st));
+               bcma_mask32(pi->d11core, D11REGOFFS(clk_ctl_st),
+                           ~(CCS_FORCEHT | CCS_HTAREQ));
 
-               W_REG(&regs->clk_ctl_st, d11_clk_ctl_st);
-
-               ai_restore_core(pi->sh->sih, origidx, intr_val);
+               bcma_write32(pi->d11core, D11REGOFFS(clk_ctl_st),
+                            d11_clk_ctl_st);
        }
 
        pi->use_int_tx_iqlo_cal_nphy =
@@ -19885,7 +19879,8 @@ void wlc_phy_rxcore_setstate_nphy(struct brcms_phy_pub *pih, u8 rxcore_bitmask)
        if (!pi->sh->clk)
                return;
 
-       suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+       suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
+                        MCTL_EN_MAC));
        if (!suspend)
                wlapi_suspend_mac_and_wait(pi->sh->physhim);
 
@@ -21263,28 +21258,28 @@ wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec,
        val = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand;
        if (CHSPEC_IS5G(chanspec) && !val) {
 
-               val = R_REG(&pi->regs->psm_phy_hdr_param);
-               W_REG(&pi->regs->psm_phy_hdr_param,
+               val = bcma_read16(pi->d11core, D11REGOFFS(psm_phy_hdr_param));
+               bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param),
                      (val | MAC_PHY_FORCE_CLK));
 
                or_phy_reg(pi, (NPHY_TO_BPHY_OFF + BPHY_BB_CONFIG),
                           (BBCFG_RESETCCA | BBCFG_RESETRX));
 
-               W_REG(&pi->regs->psm_phy_hdr_param, val);
+               bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param), val);
 
                or_phy_reg(pi, 0x09, NPHY_BandControl_currentBand);
        } else if (!CHSPEC_IS5G(chanspec) && val) {
 
                and_phy_reg(pi, 0x09, ~NPHY_BandControl_currentBand);
 
-               val = R_REG(&pi->regs->psm_phy_hdr_param);
-               W_REG(&pi->regs->psm_phy_hdr_param,
+               val = bcma_read16(pi->d11core, D11REGOFFS(psm_phy_hdr_param));
+               bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param),
                      (val | MAC_PHY_FORCE_CLK));
 
                and_phy_reg(pi, (NPHY_TO_BPHY_OFF + BPHY_BB_CONFIG),
                            (u16) (~(BBCFG_RESETCCA | BBCFG_RESETRX)));
 
-               W_REG(&pi->regs->psm_phy_hdr_param, val);
+               bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param), val);
        }
 
        write_phy_reg(pi, 0x1ce, ci->PHY_BW1a);
@@ -21342,24 +21337,23 @@ wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec,
                        spuravoid = 1;
 
                wlapi_bmac_core_phypll_ctl(pi->sh->physhim, false);
-               si_pmu_spuravoid(pi->sh->sih, spuravoid);
+               si_pmu_spuravoid_pllupdate(pi->sh->sih, spuravoid);
                wlapi_bmac_core_phypll_ctl(pi->sh->physhim, true);
 
                if ((pi->sh->chip == BCM43224_CHIP_ID) ||
                    (pi->sh->chip == BCM43225_CHIP_ID)) {
-
                        if (spuravoid == 1) {
-
-                               W_REG(&pi->regs->tsf_clk_frac_l,
-                                     0x5341);
-                               W_REG(&pi->regs->tsf_clk_frac_h,
-                                     0x8);
+                               bcma_write16(pi->d11core,
+                                            D11REGOFFS(tsf_clk_frac_l),
+                                            0x5341);
+                               bcma_write16(pi->d11core,
+                                            D11REGOFFS(tsf_clk_frac_h), 0x8);
                        } else {
-
-                               W_REG(&pi->regs->tsf_clk_frac_l,
-                                     0x8889);
-                               W_REG(&pi->regs->tsf_clk_frac_h,
-                                     0x8);
+                               bcma_write16(pi->d11core,
+                                            D11REGOFFS(tsf_clk_frac_l),
+                                            0x8889);
+                               bcma_write16(pi->d11core,
+                                            D11REGOFFS(tsf_clk_frac_h), 0x8);
                        }
                }
 
@@ -21499,13 +21493,13 @@ void wlc_phy_antsel_init(struct brcms_phy_pub *ppi, bool lut_init)
 
                ai_gpiocontrol(pi->sh->sih, mask, mask, GPIO_DRV_PRIORITY);
 
-               mc = R_REG(&pi->regs->maccontrol);
+               mc = bcma_read32(pi->d11core, D11REGOFFS(maccontrol));
                mc &= ~MCTL_GPOUT_SEL_MASK;
-               W_REG(&pi->regs->maccontrol, mc);
+               bcma_write32(pi->d11core, D11REGOFFS(maccontrol), mc);
 
-               OR_REG(&pi->regs->psm_gpio_oe, mask);
+               bcma_set16(pi->d11core, D11REGOFFS(psm_gpio_oe), mask);
 
-               AND_REG(&pi->regs->psm_gpio_out, ~mask);
+               bcma_mask16(pi->d11core, D11REGOFFS(psm_gpio_out), ~mask);
 
                if (lut_init) {
                        write_phy_reg(pi, 0xf8, 0x02d8);
@@ -21522,9 +21516,8 @@ u16 wlc_phy_classifier_nphy(struct brcms_phy *pi, u16 mask, u16 val)
        bool suspended = false;
 
        if (D11REV_IS(pi->sh->corerev, 16)) {
-               suspended =
-                       (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) ?
-                       false : true;
+               suspended = (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
+                            MCTL_EN_MAC) ? false : true;
                if (!suspended)
                        wlapi_suspend_mac_and_wait(pi->sh->physhim);
        }
@@ -25383,7 +25376,8 @@ static void wlc_phy_a4(struct brcms_phy *pi, bool full_cal)
        if (pi->nphy_papd_skip == 1)
                return;
 
-       phy_b3 = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+       phy_b3 = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
+                       MCTL_EN_MAC));
        if (!phy_b3)
                wlapi_suspend_mac_and_wait(pi->sh->physhim);
 
@@ -28357,7 +28351,7 @@ void wlc_phy_txpower_recalc_target_nphy(struct brcms_phy *pi)
 
        if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) {
                wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK);
-               (void)R_REG(&pi->regs->maccontrol);
+               (void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol));
                udelay(1);
        }
 
index 12ba575f578559031226a91a7555c44ee33d6698..4931d29d077bf6e45b6ff1b5ed2045aa7102af61 100644 (file)
@@ -115,10 +115,10 @@ static void si_pmu_res_masks(struct si_pub *sih, u32 * pmin, u32 * pmax)
        uint rsrcs;
 
        /* # resources */
-       rsrcs = (sih->pmucaps & PCAP_RC_MASK) >> PCAP_RC_SHIFT;
+       rsrcs = (ai_get_pmucaps(sih) & PCAP_RC_MASK) >> PCAP_RC_SHIFT;
 
        /* determine min/max rsrc masks */
-       switch (sih->chip) {
+       switch (ai_get_chip_id(sih)) {
        case BCM43224_CHIP_ID:
        case BCM43225_CHIP_ID:
                /* ??? */
@@ -139,75 +139,84 @@ static void si_pmu_res_masks(struct si_pub *sih, u32 * pmin, u32 * pmax)
        *pmax = max_mask;
 }
 
-static void
-si_pmu_spuravoid_pllupdate(struct si_pub *sih, struct chipcregs __iomem *cc,
-                          u8 spuravoid)
+void si_pmu_spuravoid_pllupdate(struct si_pub *sih, u8 spuravoid)
 {
        u32 tmp = 0;
+       struct bcma_device *core;
 
-       switch (sih->chip) {
+       /* switch to chipc */
+       core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0);
+
+       switch (ai_get_chip_id(sih)) {
        case BCM43224_CHIP_ID:
        case BCM43225_CHIP_ID:
                if (spuravoid == 1) {
-                       W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
-                       W_REG(&cc->pllcontrol_data, 0x11500010);
-                       W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
-                       W_REG(&cc->pllcontrol_data, 0x000C0C06);
-                       W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
-                       W_REG(&cc->pllcontrol_data, 0x0F600a08);
-                       W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
-                       W_REG(&cc->pllcontrol_data, 0x00000000);
-                       W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
-                       W_REG(&cc->pllcontrol_data, 0x2001E920);
-                       W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
-                       W_REG(&cc->pllcontrol_data, 0x88888815);
+                       bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
+                                    PMU1_PLL0_PLLCTL0);
+                       bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
+                                    0x11500010);
+                       bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
+                                    PMU1_PLL0_PLLCTL1);
+                       bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
+                                    0x000C0C06);
+                       bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
+                                    PMU1_PLL0_PLLCTL2);
+                       bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
+                                    0x0F600a08);
+                       bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
+                                    PMU1_PLL0_PLLCTL3);
+                       bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
+                                    0x00000000);
+                       bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
+                                    PMU1_PLL0_PLLCTL4);
+                       bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
+                                    0x2001E920);
+                       bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
+                                    PMU1_PLL0_PLLCTL5);
+                       bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
+                                    0x88888815);
                } else {
-                       W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
-                       W_REG(&cc->pllcontrol_data, 0x11100010);
-                       W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
-                       W_REG(&cc->pllcontrol_data, 0x000c0c06);
-                       W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
-                       W_REG(&cc->pllcontrol_data, 0x03000a08);
-                       W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
-                       W_REG(&cc->pllcontrol_data, 0x00000000);
-                       W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
-                       W_REG(&cc->pllcontrol_data, 0x200005c0);
-                       W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
-                       W_REG(&cc->pllcontrol_data, 0x88888815);
+                       bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
+                                    PMU1_PLL0_PLLCTL0);
+                       bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
+                                    0x11100010);
+                       bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
+                                    PMU1_PLL0_PLLCTL1);
+                       bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
+                                    0x000c0c06);
+                       bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
+                                    PMU1_PLL0_PLLCTL2);
+                       bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
+                                    0x03000a08);
+                       bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
+                                    PMU1_PLL0_PLLCTL3);
+                       bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
+                                    0x00000000);
+                       bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
+                                    PMU1_PLL0_PLLCTL4);
+                       bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
+                                    0x200005c0);
+                       bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
+                                    PMU1_PLL0_PLLCTL5);
+                       bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
+                                    0x88888815);
                }
                tmp = 1 << 10;
                break;
 
-               W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
-               W_REG(&cc->pllcontrol_data, 0x11100008);
-               W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
-               W_REG(&cc->pllcontrol_data, 0x0c000c06);
-               W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
-               W_REG(&cc->pllcontrol_data, 0x03000a08);
-               W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
-               W_REG(&cc->pllcontrol_data, 0x00000000);
-               W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
-               W_REG(&cc->pllcontrol_data, 0x200005c0);
-               W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
-               W_REG(&cc->pllcontrol_data, 0x88888855);
-
-               tmp = 1 << 10;
-               break;
-
        default:
                /* bail out */
                return;
        }
 
-       tmp |= R_REG(&cc->pmucontrol);
-       W_REG(&cc->pmucontrol, tmp);
+       bcma_set32(core, CHIPCREGOFFS(pmucontrol), tmp);
 }
 
 u16 si_pmu_fast_pwrup_delay(struct si_pub *sih)
 {
        uint delay = PMU_MAX_TRANSITION_DLY;
 
-       switch (sih->chip) {
+       switch (ai_get_chip_id(sih)) {
        case BCM43224_CHIP_ID:
        case BCM43225_CHIP_ID:
        case BCM4313_CHIP_ID:
@@ -220,54 +229,35 @@ u16 si_pmu_fast_pwrup_delay(struct si_pub *sih)
        return (u16) delay;
 }
 
-void si_pmu_sprom_enable(struct si_pub *sih, bool enable)
-{
-       struct chipcregs __iomem *cc;
-       uint origidx;
-
-       /* Remember original core before switch to chipc */
-       origidx = ai_coreidx(sih);
-       cc = ai_setcoreidx(sih, SI_CC_IDX);
-
-       /* Return to original core */
-       ai_setcoreidx(sih, origidx);
-}
-
 /* Read/write a chipcontrol reg */
 u32 si_pmu_chipcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val)
 {
-       ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, chipcontrol_addr),
-                  ~0, reg);
-       return ai_corereg(sih, SI_CC_IDX,
-                         offsetof(struct chipcregs, chipcontrol_data), mask,
-                         val);
+       ai_cc_reg(sih, offsetof(struct chipcregs, chipcontrol_addr), ~0, reg);
+       return ai_cc_reg(sih, offsetof(struct chipcregs, chipcontrol_data),
+                        mask, val);
 }
 
 /* Read/write a regcontrol reg */
 u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val)
 {
-       ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, regcontrol_addr),
-                  ~0, reg);
-       return ai_corereg(sih, SI_CC_IDX,
-                         offsetof(struct chipcregs, regcontrol_data), mask,
-                         val);
+       ai_cc_reg(sih, offsetof(struct chipcregs, regcontrol_addr), ~0, reg);
+       return ai_cc_reg(sih, offsetof(struct chipcregs, regcontrol_data),
+                        mask, val);
 }
 
 /* Read/write a pllcontrol reg */
 u32 si_pmu_pllcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val)
 {
-       ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, pllcontrol_addr),
-                  ~0, reg);
-       return ai_corereg(sih, SI_CC_IDX,
-                         offsetof(struct chipcregs, pllcontrol_data), mask,
-                         val);
+       ai_cc_reg(sih, offsetof(struct chipcregs, pllcontrol_addr), ~0, reg);
+       return ai_cc_reg(sih, offsetof(struct chipcregs, pllcontrol_data),
+                        mask, val);
 }
 
 /* PMU PLL update */
 void si_pmu_pllupd(struct si_pub *sih)
 {
-       ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, pmucontrol),
-                  PCTL_PLL_PLLCTL_UPD, PCTL_PLL_PLLCTL_UPD);
+       ai_cc_reg(sih, offsetof(struct chipcregs, pmucontrol),
+                 PCTL_PLL_PLLCTL_UPD, PCTL_PLL_PLLCTL_UPD);
 }
 
 /* query alp/xtal clock frequency */
@@ -276,10 +266,10 @@ u32 si_pmu_alp_clock(struct si_pub *sih)
        u32 clock = ALP_CLOCK;
 
        /* bail out with default */
-       if (!(sih->cccaps & CC_CAP_PMU))
+       if (!(ai_get_cccaps(sih) & CC_CAP_PMU))
                return clock;
 
-       switch (sih->chip) {
+       switch (ai_get_chip_id(sih)) {
        case BCM43224_CHIP_ID:
        case BCM43225_CHIP_ID:
        case BCM4313_CHIP_ID:
@@ -293,95 +283,29 @@ u32 si_pmu_alp_clock(struct si_pub *sih)
        return clock;
 }
 
-void si_pmu_spuravoid(struct si_pub *sih, u8 spuravoid)
-{
-       struct chipcregs __iomem *cc;
-       uint origidx, intr_val;
-
-       /* Remember original core before switch to chipc */
-       cc = (struct chipcregs __iomem *)
-                       ai_switch_core(sih, CC_CORE_ID, &origidx, &intr_val);
-
-       /* update the pll changes */
-       si_pmu_spuravoid_pllupdate(sih, cc, spuravoid);
-
-       /* Return to original core */
-       ai_restore_core(sih, origidx, intr_val);
-}
-
 /* initialize PMU */
 void si_pmu_init(struct si_pub *sih)
 {
-       struct chipcregs __iomem *cc;
-       uint origidx;
+       struct bcma_device *core;
 
-       /* Remember original core before switch to chipc */
-       origidx = ai_coreidx(sih);
-       cc = ai_setcoreidx(sih, SI_CC_IDX);
-
-       if (sih->pmurev == 1)
-               AND_REG(&cc->pmucontrol, ~PCTL_NOILP_ON_WAIT);
-       else if (sih->pmurev >= 2)
-               OR_REG(&cc->pmucontrol, PCTL_NOILP_ON_WAIT);
+       /* select chipc */
+       core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0);
 
-       /* Return to original core */
-       ai_setcoreidx(sih, origidx);
-}
-
-/* initialize PMU chip controls and other chip level stuff */
-void si_pmu_chip_init(struct si_pub *sih)
-{
-       uint origidx;
-
-       /* Gate off SPROM clock and chip select signals */
-       si_pmu_sprom_enable(sih, false);
-
-       /* Remember original core */
-       origidx = ai_coreidx(sih);
-
-       /* Return to original core */
-       ai_setcoreidx(sih, origidx);
-}
-
-/* initialize PMU switch/regulators */
-void si_pmu_swreg_init(struct si_pub *sih)
-{
-}
-
-/* initialize PLL */
-void si_pmu_pll_init(struct si_pub *sih, uint xtalfreq)
-{
-       struct chipcregs __iomem *cc;
-       uint origidx;
-
-       /* Remember original core before switch to chipc */
-       origidx = ai_coreidx(sih);
-       cc = ai_setcoreidx(sih, SI_CC_IDX);
-
-       switch (sih->chip) {
-       case BCM4313_CHIP_ID:
-       case BCM43224_CHIP_ID:
-       case BCM43225_CHIP_ID:
-               /* ??? */
-               break;
-       default:
-               break;
-       }
-
-       /* Return to original core */
-       ai_setcoreidx(sih, origidx);
+       if (ai_get_pmurev(sih) == 1)
+               bcma_mask32(core, CHIPCREGOFFS(pmucontrol),
+                           ~PCTL_NOILP_ON_WAIT);
+       else if (ai_get_pmurev(sih) >= 2)
+               bcma_set32(core, CHIPCREGOFFS(pmucontrol), PCTL_NOILP_ON_WAIT);
 }
 
 /* initialize PMU resources */
 void si_pmu_res_init(struct si_pub *sih)
 {
-       struct chipcregs __iomem *cc;
-       uint origidx;
+       struct bcma_device *core;
        u32 min_mask = 0, max_mask = 0;
 
-       /* Remember original core before switch to chipc */
-       origidx = ai_coreidx(sih);
-       cc = ai_setcoreidx(sih, SI_CC_IDX);
+       /* select to chipc */
+       core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0);
 
        /* Determine min/max rsrc masks */
        si_pmu_res_masks(sih, &min_mask, &max_mask);
@@ -391,55 +315,50 @@ void si_pmu_res_init(struct si_pub *sih)
        /* Program max resource mask */
 
        if (max_mask)
-               W_REG(&cc->max_res_mask, max_mask);
+               bcma_write32(core, CHIPCREGOFFS(max_res_mask), max_mask);
 
        /* Program min resource mask */
 
        if (min_mask)
-               W_REG(&cc->min_res_mask, min_mask);
+               bcma_write32(core, CHIPCREGOFFS(min_res_mask), min_mask);
 
        /* Add some delay; allow resources to come up and settle. */
        mdelay(2);
-
-       /* Return to original core */
-       ai_setcoreidx(sih, origidx);
 }
 
 u32 si_pmu_measure_alpclk(struct si_pub *sih)
 {
-       struct chipcregs __iomem *cc;
-       uint origidx;
+       struct bcma_device *core;
        u32 alp_khz;
 
-       if (sih->pmurev < 10)
+       if (ai_get_pmurev(sih) < 10)
                return 0;
 
        /* Remember original core before switch to chipc */
-       origidx = ai_coreidx(sih);
-       cc = ai_setcoreidx(sih, SI_CC_IDX);
+       core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0);
 
-       if (R_REG(&cc->pmustatus) & PST_EXTLPOAVAIL) {
+       if (bcma_read32(core, CHIPCREGOFFS(pmustatus)) & PST_EXTLPOAVAIL) {
                u32 ilp_ctr, alp_hz;
 
                /*
                 * Enable the reg to measure the freq,
                 * in case it was disabled before
                 */
-               W_REG(&cc->pmu_xtalfreq,
-                     1U << PMU_XTALFREQ_REG_MEASURE_SHIFT);
+               bcma_write32(core, CHIPCREGOFFS(pmu_xtalfreq),
+                           1U << PMU_XTALFREQ_REG_MEASURE_SHIFT);
 
                /* Delay for well over 4 ILP clocks */
                udelay(1000);
 
                /* Read the latched number of ALP ticks per 4 ILP ticks */
-               ilp_ctr =
-                   R_REG(&cc->pmu_xtalfreq) & PMU_XTALFREQ_REG_ILPCTR_MASK;
+               ilp_ctr = bcma_read32(core, CHIPCREGOFFS(pmu_xtalfreq)) &
+                         PMU_XTALFREQ_REG_ILPCTR_MASK;
 
                /*
                 * Turn off the PMU_XTALFREQ_REG_MEASURE_SHIFT
                 * bit to save power
                 */
-               W_REG(&cc->pmu_xtalfreq, 0);
+               bcma_write32(core, CHIPCREGOFFS(pmu_xtalfreq), 0);
 
                /* Calculate ALP frequency */
                alp_hz = (ilp_ctr * EXT_ILP_HZ) / 4;
@@ -452,8 +371,5 @@ u32 si_pmu_measure_alpclk(struct si_pub *sih)
        } else
                alp_khz = 0;
 
-       /* Return to original core */
-       ai_setcoreidx(sih, origidx);
-
        return alp_khz;
 }
index 3a08c620640e7272ebe474314a686b1cedd53925..3e39c5e0f9ff3ed500e8a91115758783da038980 100644 (file)
@@ -26,13 +26,10 @@ extern u32 si_pmu_chipcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val);
 extern u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val);
 extern u32 si_pmu_alp_clock(struct si_pub *sih);
 extern void si_pmu_pllupd(struct si_pub *sih);
-extern void si_pmu_spuravoid(struct si_pub *sih, u8 spuravoid);
+extern void si_pmu_spuravoid_pllupdate(struct si_pub *sih, u8 spuravoid);
 extern u32 si_pmu_pllcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val);
 extern void si_pmu_init(struct si_pub *sih);
-extern void si_pmu_chip_init(struct si_pub *sih);
-extern void si_pmu_pll_init(struct si_pub *sih, u32 xtalfreq);
 extern void si_pmu_res_init(struct si_pub *sih);
-extern void si_pmu_swreg_init(struct si_pub *sih);
 extern u32 si_pmu_measure_alpclk(struct si_pub *sih);
 
 #endif /* _BRCM_PMU_H_ */
index 21ccf3a039873cf777595e0e5a71ff8eb93a94a1..f0038ad7d7bf7438a244001416f86615d87284de 100644 (file)
@@ -17,6 +17,7 @@
 #ifndef _BRCM_PUB_H_
 #define _BRCM_PUB_H_
 
+#include <linux/bcma/bcma.h>
 #include <brcmu_wifi.h>
 #include "types.h"
 #include "defs.h"
@@ -530,9 +531,8 @@ struct brcms_antselcfg {
 
 /* common functions for every port */
 extern struct brcms_c_info *
-brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device, uint unit,
-              bool piomode, void __iomem *regsva, struct pci_dev *btparam,
-              uint *perr);
+brcms_c_attach(struct brcms_info *wl, struct bcma_device *core, uint unit,
+              bool piomode, uint *perr);
 extern uint brcms_c_detach(struct brcms_c_info *wlc);
 extern int brcms_c_up(struct brcms_c_info *wlc);
 extern uint brcms_c_down(struct brcms_c_info *wlc);
index b6987ea9fc689b6b4351ab83cf3af9f67aa32e3a..61092156755e0a77984736df7a1ac524bb074ef5 100644 (file)
@@ -586,17 +586,6 @@ static const struct brcms_sromvar perpath_pci_sromvars[] = {
  * shared between devices. */
 static u8 brcms_srom_crc8_table[CRC8_TABLE_SIZE];
 
-static u8 __iomem *
-srom_window_address(struct si_pub *sih, u8 __iomem *curmap)
-{
-       if (sih->ccrev < 32)
-               return curmap + PCI_BAR0_SPROM_OFFSET;
-       if (sih->cccaps & CC_CAP_SROM)
-               return curmap + PCI_16KB0_CCREGS_OFFSET + CC_SROM_OTP;
-
-       return NULL;
-}
-
 static uint mask_shift(u16 mask)
 {
        uint i;
@@ -779,17 +768,27 @@ _initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list)
  * Return 0 on success, nonzero on error.
  */
 static int
-sprom_read_pci(struct si_pub *sih, u8 __iomem *sprom, uint wordoff,
-              u16 *buf, uint nwords, bool check_crc)
+sprom_read_pci(struct si_pub *sih, u16 *buf, uint nwords, bool check_crc)
 {
        int err = 0;
        uint i;
        u8 *bbuf = (u8 *)buf; /* byte buffer */
        uint nbytes = nwords << 1;
+       struct bcma_device *core;
+       uint sprom_offset;
+
+       /* determine core to read */
+       if (ai_get_ccrev(sih) < 32) {
+               core = ai_findcore(sih, BCMA_CORE_80211, 0);
+               sprom_offset = PCI_BAR0_SPROM_OFFSET;
+       } else {
+               core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0);
+               sprom_offset = CHIPCREGOFFS(sromotp);
+       }
 
        /* read the sprom in bytes */
        for (i = 0; i < nbytes; i++)
-               bbuf[i] = readb(sprom+i);
+               bbuf[i] = bcma_read8(core, sprom_offset+i);
 
        if (buf[0] == 0xffff)
                /*
@@ -851,10 +850,9 @@ static int otp_read_pci(struct si_pub *sih, u16 *buf, uint nwords)
  * Initialize nonvolatile variable table from sprom.
  * Return 0 on success, nonzero on error.
  */
-static int initvars_srom_pci(struct si_pub *sih, void __iomem *curmap)
+int srom_var_init(struct si_pub *sih)
 {
        u16 *srom;
-       u8 __iomem *sromwindow;
        u8 sromrev = 0;
        u32 sr;
        int err = 0;
@@ -866,12 +864,9 @@ static int initvars_srom_pci(struct si_pub *sih, void __iomem *curmap)
        if (!srom)
                return -ENOMEM;
 
-       sromwindow = srom_window_address(sih, curmap);
-
        crc8_populate_lsb(brcms_srom_crc8_table, SROM_CRC8_POLY);
        if (ai_is_sprom_available(sih)) {
-               err = sprom_read_pci(sih, sromwindow, 0, srom,
-                                    SROM4_WORDS, true);
+               err = sprom_read_pci(sih, srom, SROM4_WORDS, true);
 
                if (err == 0)
                        /* srom read and passed crc */
@@ -921,21 +916,6 @@ void srom_free_vars(struct si_pub *sih)
                kfree(entry);
        }
 }
-/*
- * Initialize local vars from the right source for this platform.
- * Return 0 on success, nonzero on error.
- */
-int srom_var_init(struct si_pub *sih, void __iomem *curmap)
-{
-       uint len;
-
-       len = 0;
-
-       if (curmap != NULL)
-               return initvars_srom_pci(sih, curmap);
-
-       return -EINVAL;
-}
 
 /*
  * Search the name=value vars for a specific one and return its value.
index c81df9798e50ac606dc4c9e15122f8ba58d28354..f2a58f262c990ce299d376300aaeaf22d12bae18 100644 (file)
@@ -20,7 +20,7 @@
 #include "types.h"
 
 /* Prototypes */
-extern int srom_var_init(struct si_pub *sih, void __iomem *curmap);
+extern int srom_var_init(struct si_pub *sih);
 extern void srom_free_vars(struct si_pub *sih);
 
 extern int srom_read(struct si_pub *sih, uint bus, void *curmap,
index 27a814b074625a64d6112ac3a3df9a8d06cc607c..e11ae83111e499411670af3ac4fc72158ba77d25 100644 (file)
@@ -250,66 +250,18 @@ do {                                              \
                wiphy_err(dev, "%s: " fmt, __func__, ##args);   \
 } while (0)
 
-/*
- * Register access macros.
- *
- * These macro's take a pointer to the address to read as one of their
- * arguments. The macro itself deduces the size of the IO transaction (u8, u16
- * or u32). Advantage of this approach in combination with using a struct to
- * define the registers in a register block, is that access size and access
- * location are defined in only one spot. This reduces the risk of the
- * programmer trying to use an unsupported transaction size on a register.
- *
- */
-
-#define R_REG(r) \
-       ({ \
-               __typeof(*(r)) __osl_v; \
-               switch (sizeof(*(r))) { \
-               case sizeof(u8): \
-                       __osl_v = readb((u8 __iomem *)(r)); \
-                       break; \
-               case sizeof(u16): \
-                       __osl_v = readw((u16 __iomem *)(r)); \
-                       break; \
-               case sizeof(u32): \
-                       __osl_v = readl((u32 __iomem *)(r)); \
-                       break; \
-               } \
-               __osl_v; \
-       })
-
-#define W_REG(r, v) do { \
-               switch (sizeof(*(r))) { \
-               case sizeof(u8):        \
-                       writeb((u8)((v) & 0xFF), (u8 __iomem *)(r)); \
-                       break; \
-               case sizeof(u16):       \
-                       writew((u16)((v) & 0xFFFF), (u16 __iomem *)(r)); \
-                       break; \
-               case sizeof(u32):       \
-                       writel((u32)(v), (u32 __iomem *)(r)); \
-                       break; \
-               } \
-       } while (0)
-
 #ifdef CONFIG_BCM47XX
 /*
  * bcm4716 (which includes 4717 & 4718), plus 4706 on PCIe can reorder
  * transactions. As a fix, a read after write is performed on certain places
  * in the code. Older chips and the newer 5357 family don't require this fix.
  */
-#define W_REG_FLUSH(r, v)      ({ W_REG((r), (v)); (void)R_REG(r); })
+#define bcma_wflush16(c, o, v) \
+       ({ bcma_write16(c, o, v); (void)bcma_read16(c, o); })
 #else
-#define W_REG_FLUSH(r, v)      W_REG((r), (v))
+#define bcma_wflush16(c, o, v) bcma_write16(c, o, v)
 #endif                         /* CONFIG_BCM47XX */
 
-#define AND_REG(r, v)  W_REG((r), R_REG(r) & (v))
-#define OR_REG(r, v)   W_REG((r), R_REG(r) | (v))
-
-#define SET_REG(r, mask, val) \
-               W_REG((r), ((R_REG(r) & ~(mask)) | (val)))
-
 /* multi-bool data type: set of bools, mbool is true if any is set */
 
 /* set one bool */
index fefabc39e646d9bf72552c2b12a7c4c0088db584..f96834a7c055df387cf234efd5153d6994868c79 100644 (file)
@@ -19,6 +19,8 @@
 
 #include "defs.h"              /* for PAD macro */
 
+#define CHIPCREGOFFS(field)    offsetof(struct chipcregs, field)
+
 struct chipcregs {
        u32 chipid;             /* 0x0 */
        u32 capabilities;
index 57703d5209d7873c1a9dd5882ced9cea0d1ae3b8..ae08498dfcad98a91311e128ab9569f0f7c9534b 100644 (file)
@@ -102,12 +102,28 @@ config IWLWIFI_DEVICE_TRACING
          occur.
 endmenu
 
-config IWLWIFI_DEVICE_SVTOOL
-       bool "iwlwifi device svtool support"
+config IWLWIFI_DEVICE_TESTMODE
+       def_bool y
        depends on IWLWIFI
-       select NL80211_TESTMODE
+       depends on NL80211_TESTMODE
        help
-         This option enables the svtool support for iwlwifi device through
-         NL80211_TESTMODE. svtool is a software validation tool that runs in
-         the user space and interacts with the device in the kernel space
-         through the generic netlink message via NL80211_TESTMODE channel.
+         This option enables the testmode support for iwlwifi device through
+         NL80211_TESTMODE. This provide the capabilities of enable user space
+         validation applications to interacts with the device through the
+         generic netlink message via NL80211_TESTMODE channel.
+
+config IWLWIFI_P2P
+       bool "iwlwifi experimental P2P support"
+       depends on IWLWIFI
+       help
+         This option enables experimental P2P support for some devices
+         based on microcode support. Since P2P support is still under
+         development, this option may even enable it for some devices
+         now that turn out to not support it in the future due to
+         microcode restrictions.
+
+         To determine if your microcode supports the experimental P2P
+         offered by this option, check if the driver advertises AP
+         support when it is loaded.
+
+         Say Y only if you want to experiment with P2P.
index 86344cefd32fd4a7e3e532ead5374950ca25f8f7..9dc84a7354dbbde1cdec1560dc91d019039c5feb 100644 (file)
@@ -18,7 +18,7 @@ iwlwifi-objs          += iwl-trans-pcie.o iwl-trans-pcie-rx.o iwl-trans-pcie-tx.o
 
 iwlwifi-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
 iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
-iwlwifi-$(CONFIG_IWLWIFI_DEVICE_SVTOOL) += iwl-testmode.o
+iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TESTMODE) += iwl-testmode.o
 
 CFLAGS_iwl-devtrace.o := -I$(src)
 
index cf2fb47529b3a7d473a30d3e04a9e04b3a4d5b4d..6706d7c10bd804761d3fc66da4363457b11aee7c 100644 (file)
@@ -134,10 +134,10 @@ static struct iwl_sensitivity_ranges iwl5150_sensitivity = {
 
 #define IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF  (-5)
 
-static s32 iwl_temp_calib_to_offset(struct iwl_priv *priv)
+static s32 iwl_temp_calib_to_offset(struct iwl_shared *shrd)
 {
        u16 temperature, voltage;
-       __le16 *temp_calib = (__le16 *)iwl_eeprom_query_addr(priv,
+       __le16 *temp_calib = (__le16 *)iwl_eeprom_query_addr(shrd,
                                EEPROM_KELVIN_TEMPERATURE);
 
        temperature = le16_to_cpu(temp_calib[0]);
@@ -151,7 +151,7 @@ static void iwl5150_set_ct_threshold(struct iwl_priv *priv)
 {
        const s32 volt2temp_coef = IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF;
        s32 threshold = (s32)CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY) -
-                       iwl_temp_calib_to_offset(priv);
+                       iwl_temp_calib_to_offset(priv->shrd);
 
        hw_params(priv).ct_kill_threshold = threshold * volt2temp_coef;
 }
@@ -223,7 +223,7 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv)
 static void iwl5150_temperature(struct iwl_priv *priv)
 {
        u32 vt = 0;
-       s32 offset =  iwl_temp_calib_to_offset(priv);
+       s32 offset =  iwl_temp_calib_to_offset(priv->shrd);
 
        vt = le32_to_cpu(priv->statistics.common.temperature);
        vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset;
index 617ad1c0df61f74cebaefc425815ac3de99057ab..3e277b6774f13bcf467b4e7de0b7b76939a96704 100644 (file)
@@ -81,7 +81,7 @@ static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
 static void iwl6050_additional_nic_config(struct iwl_priv *priv)
 {
        /* Indicate calibration version to uCode. */
-       if (iwlagn_eeprom_calib_version(priv) >= 6)
+       if (iwl_eeprom_calib_version(priv->shrd) >= 6)
                iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG,
                                CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6);
 }
@@ -89,7 +89,7 @@ static void iwl6050_additional_nic_config(struct iwl_priv *priv)
 static void iwl6150_additional_nic_config(struct iwl_priv *priv)
 {
        /* Indicate calibration version to uCode. */
-       if (iwlagn_eeprom_calib_version(priv) >= 6)
+       if (iwl_eeprom_calib_version(priv->shrd) >= 6)
                iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG,
                                CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6);
        iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG,
index 4d0210594956fae5200767d37663d77112eb55f0..16971a020297dab59e8efc8c99a052bd65ee384c 100644 (file)
@@ -82,7 +82,7 @@ struct statistics_general_data {
        u32 beacon_energy_c;
 };
 
-int iwl_send_calib_results(struct iwl_priv *priv)
+int iwl_send_calib_results(struct iwl_trans *trans)
 {
        struct iwl_host_cmd hcmd = {
                .id = REPLY_PHY_CALIBRATION_CMD,
@@ -90,15 +90,15 @@ int iwl_send_calib_results(struct iwl_priv *priv)
        };
        struct iwl_calib_result *res;
 
-       list_for_each_entry(res, &priv->calib_results, list) {
+       list_for_each_entry(res, &trans->calib_results, list) {
                int ret;
 
                hcmd.len[0] = res->cmd_len;
                hcmd.data[0] = &res->hdr;
                hcmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
-               ret = iwl_trans_send_cmd(trans(priv), &hcmd);
+               ret = iwl_trans_send_cmd(trans, &hcmd);
                if (ret) {
-                       IWL_ERR(priv, "Error %d on calib cmd %d\n",
+                       IWL_ERR(trans, "Error %d on calib cmd %d\n",
                                ret, res->hdr.op_code);
                        return ret;
                }
@@ -107,7 +107,7 @@ int iwl_send_calib_results(struct iwl_priv *priv)
        return 0;
 }
 
-int iwl_calib_set(struct iwl_priv *priv,
+int iwl_calib_set(struct iwl_trans *trans,
                  const struct iwl_calib_hdr *cmd, int len)
 {
        struct iwl_calib_result *res, *tmp;
@@ -119,7 +119,7 @@ int iwl_calib_set(struct iwl_priv *priv,
        memcpy(&res->hdr, cmd, len);
        res->cmd_len = len;
 
-       list_for_each_entry(tmp, &priv->calib_results, list) {
+       list_for_each_entry(tmp, &trans->calib_results, list) {
                if (tmp->hdr.op_code == res->hdr.op_code) {
                        list_replace(&tmp->list, &res->list);
                        kfree(tmp);
@@ -128,16 +128,16 @@ int iwl_calib_set(struct iwl_priv *priv,
        }
 
        /* wasn't in list already */
-       list_add_tail(&res->list, &priv->calib_results);
+       list_add_tail(&res->list, &trans->calib_results);
 
        return 0;
 }
 
-void iwl_calib_free_results(struct iwl_priv *priv)
+void iwl_calib_free_results(struct iwl_trans *trans)
 {
        struct iwl_calib_result *res, *tmp;
 
-       list_for_each_entry_safe(res, tmp, &priv->calib_results, list) {
+       list_for_each_entry_safe(res, tmp, &trans->calib_results, list) {
                list_del(&res->list);
                kfree(res);
        }
index 6ed806c8f80f2fb9cdf8ede9acb4c8e22bc79c5f..10275ce92bde8875f9807245cf32a0ec00addae6 100644 (file)
@@ -72,9 +72,4 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv);
 void iwl_init_sensitivity(struct iwl_priv *priv);
 void iwl_reset_run_time_calib(struct iwl_priv *priv);
 
-int iwl_send_calib_results(struct iwl_priv *priv);
-int iwl_calib_set(struct iwl_priv *priv,
-                 const struct iwl_calib_hdr *cmd, int len);
-void iwl_calib_free_results(struct iwl_priv *priv);
-
 #endif /* __iwl_calib_h__ */
index 575d1bb8e8cc4b1ab91f9797a452a0afdda7181e..057f95233567ff63bb0b554eb8ce660e0acd1ad1 100644 (file)
@@ -92,11 +92,11 @@ void iwlagn_temperature(struct iwl_priv *priv)
        iwl_tt_handler(priv);
 }
 
-u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv)
+u16 iwl_eeprom_calib_version(struct iwl_shared *shrd)
 {
        struct iwl_eeprom_calib_hdr *hdr;
 
-       hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv,
+       hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(shrd,
                                                        EEPROM_CALIB_ALL);
        return hdr->version;
 
@@ -105,7 +105,7 @@ u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv)
 /*
  * EEPROM
  */
-static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address)
+static u32 eeprom_indirect_address(const struct iwl_shared *shrd, u32 address)
 {
        u16 offset = 0;
 
@@ -114,31 +114,31 @@ static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address)
 
        switch (address & INDIRECT_TYPE_MSK) {
        case INDIRECT_HOST:
-               offset = iwl_eeprom_query16(priv, EEPROM_LINK_HOST);
+               offset = iwl_eeprom_query16(shrd, EEPROM_LINK_HOST);
                break;
        case INDIRECT_GENERAL:
-               offset = iwl_eeprom_query16(priv, EEPROM_LINK_GENERAL);
+               offset = iwl_eeprom_query16(shrd, EEPROM_LINK_GENERAL);
                break;
        case INDIRECT_REGULATORY:
-               offset = iwl_eeprom_query16(priv, EEPROM_LINK_REGULATORY);
+               offset = iwl_eeprom_query16(shrd, EEPROM_LINK_REGULATORY);
                break;
        case INDIRECT_TXP_LIMIT:
-               offset = iwl_eeprom_query16(priv, EEPROM_LINK_TXP_LIMIT);
+               offset = iwl_eeprom_query16(shrd, EEPROM_LINK_TXP_LIMIT);
                break;
        case INDIRECT_TXP_LIMIT_SIZE:
-               offset = iwl_eeprom_query16(priv, EEPROM_LINK_TXP_LIMIT_SIZE);
+               offset = iwl_eeprom_query16(shrd, EEPROM_LINK_TXP_LIMIT_SIZE);
                break;
        case INDIRECT_CALIBRATION:
-               offset = iwl_eeprom_query16(priv, EEPROM_LINK_CALIBRATION);
+               offset = iwl_eeprom_query16(shrd, EEPROM_LINK_CALIBRATION);
                break;
        case INDIRECT_PROCESS_ADJST:
-               offset = iwl_eeprom_query16(priv, EEPROM_LINK_PROCESS_ADJST);
+               offset = iwl_eeprom_query16(shrd, EEPROM_LINK_PROCESS_ADJST);
                break;
        case INDIRECT_OTHERS:
-               offset = iwl_eeprom_query16(priv, EEPROM_LINK_OTHERS);
+               offset = iwl_eeprom_query16(shrd, EEPROM_LINK_OTHERS);
                break;
        default:
-               IWL_ERR(priv, "illegal indirect type: 0x%X\n",
+               IWL_ERR(shrd->trans, "illegal indirect type: 0x%X\n",
                address & INDIRECT_TYPE_MSK);
                break;
        }
@@ -147,11 +147,11 @@ static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address)
        return (address & ADDRESS_MSK) + (offset << 1);
 }
 
-const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset)
+const u8 *iwl_eeprom_query_addr(const struct iwl_shared *shrd, size_t offset)
 {
-       u32 address = eeprom_indirect_address(priv, offset);
-       BUG_ON(address >= priv->cfg->base_params->eeprom_size);
-       return &priv->eeprom[address];
+       u32 address = eeprom_indirect_address(shrd, offset);
+       BUG_ON(address >= shrd->priv->cfg->base_params->eeprom_size);
+       return &shrd->eeprom[address];
 }
 
 struct iwl_mod_params iwlagn_mod_params = {
@@ -1157,7 +1157,7 @@ int iwlagn_suspend(struct iwl_priv *priv,
         * For QoS counters, we store the one to use next, so subtract 0x10
         * since the uCode will add 0x10 before using the value.
         */
-       for (i = 0; i < 8; i++) {
+       for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
                seq = priv->shrd->tid_data[IWL_AP_ID][i].seq_number;
                seq -= 0x10;
                wakeup_filter_cmd.qos_seq[i] = cpu_to_le16(seq);
index 359c47a4fcea457841c57e702910d4400797a22d..a23835a7797afc75e1f3415da9917af547eb1591 100644 (file)
@@ -298,7 +298,7 @@ static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data,
        } else
                return IWL_MAX_TID_COUNT;
 
-       if (unlikely(tid >= TID_MAX_LOAD_COUNT))
+       if (unlikely(tid >= IWL_MAX_TID_COUNT))
                return IWL_MAX_TID_COUNT;
 
        tl = &lq_data->load[tid];
@@ -352,7 +352,7 @@ static void rs_program_fix_rate(struct iwl_priv *priv,
        lq_sta->active_mimo2_rate  = 0x1FD0;    /* 6 - 60 MBits, no 9, no CCK */
        lq_sta->active_mimo3_rate  = 0x1FD0;    /* 6 - 60 MBits, no 9, no CCK */
 
-#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
+#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
        /* testmode has higher priority to overwirte the fixed rate */
        if (priv->tm_fixed_rate)
                lq_sta->dbg_fixed_rate = priv->tm_fixed_rate;
@@ -379,7 +379,7 @@ static u32 rs_tl_get_load(struct iwl_lq_sta *lq_data, u8 tid)
        s32 index;
        struct iwl_traffic_load *tl = NULL;
 
-       if (tid >= TID_MAX_LOAD_COUNT)
+       if (tid >= IWL_MAX_TID_COUNT)
                return 0;
 
        tl = &(lq_data->load[tid]);
@@ -444,11 +444,11 @@ static void rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid,
                              struct iwl_lq_sta *lq_data,
                              struct ieee80211_sta *sta)
 {
-       if (tid < TID_MAX_LOAD_COUNT)
+       if (tid < IWL_MAX_TID_COUNT)
                rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta);
        else
-               IWL_ERR(priv, "tid exceeds max load count: %d/%d\n",
-                       tid, TID_MAX_LOAD_COUNT);
+               IWL_ERR(priv, "tid exceeds max TID count: %d/%d\n",
+                       tid, IWL_MAX_TID_COUNT);
 }
 
 static inline int get_num_of_ant_from_rate(u32 rate_n_flags)
@@ -1081,7 +1081,7 @@ done:
        if (sta && sta->supp_rates[sband->band])
                rs_rate_scale_perform(priv, skb, sta, lq_sta);
 
-#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_IWLWIFI_DEVICE_SVTOOL)
+#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_IWLWIFI_DEVICE_TESTMODE)
        if ((priv->tm_fixed_rate) &&
            (priv->tm_fixed_rate != lq_sta->dbg_fixed_rate))
                rs_program_fix_rate(priv, lq_sta);
@@ -2904,7 +2904,7 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i
        if (sband->band == IEEE80211_BAND_5GHZ)
                lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
        lq_sta->is_agg = 0;
-#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
+#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
        priv->tm_fixed_rate = 0;
 #endif
 #ifdef CONFIG_MAC80211_DEBUGFS
index f4f6deb829ae1d5d7dee97afb422e0de6c31115c..6675b3c816d989e3a7f47f1a8f025fac98aab67e 100644 (file)
@@ -281,7 +281,6 @@ enum {
 #define TID_QUEUE_CELL_SPACING 50      /*mS */
 #define TID_QUEUE_MAX_SIZE     20
 #define TID_ROUND_VALUE                5       /* mS */
-#define TID_MAX_LOAD_COUNT     8
 
 #define TID_MAX_TIME_DIFF ((TID_QUEUE_MAX_SIZE - 1) * TID_QUEUE_CELL_SPACING)
 #define TIME_WRAP_AROUND(x, y) (((y) > (x)) ? (y) - (x) : (0-(x)) + (y))
@@ -402,7 +401,7 @@ struct iwl_lq_sta {
 
        struct iwl_link_quality_cmd lq;
        struct iwl_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */
-       struct iwl_traffic_load load[TID_MAX_LOAD_COUNT];
+       struct iwl_traffic_load load[IWL_MAX_TID_COUNT];
        u8 tx_agg_tid_en;
 #ifdef CONFIG_MAC80211_DEBUGFS
        struct dentry *rs_sta_dbgfs_scale_table_file;
index 90c55ea4cc39a05309f909a1c3986acf5b04c7a0..9001c23f27bb1f6a8f4e8b42265ab46d6e489a42 100644 (file)
@@ -1165,7 +1165,7 @@ int iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
                                pkt->hdr.cmd);
                        w->triggered = true;
                        if (w->fn)
-                               w->fn(priv, pkt, w->fn_data);
+                               w->fn(trans(priv), pkt, w->fn_data);
                }
                spin_unlock(&priv->shrd->notif_wait_lock);
 
index 466e4ab544f7b7bb4379e598342b6c75d5833aef..d21f535a3b4fdd84fcafd600e2945243958b128d 100644 (file)
@@ -610,8 +610,8 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
                        if (ctx->ht.enabled) {
                                /* if HT40 is used, it should not change
                                 * after associated except channel switch */
-                               if (iwl_is_associated_ctx(ctx) &&
-                                    !ctx->ht.is_40mhz)
+                               if (!ctx->ht.is_40mhz ||
+                                               !iwl_is_associated_ctx(ctx))
                                        iwlagn_config_ht40(conf, ctx);
                        } else
                                ctx->ht.is_40mhz = false;
index 626ed701100e014430ed468b2d04bdcbcf2c5700..63d948d21c04895ba0944a4b25ccb04771d87b24 100644 (file)
@@ -135,8 +135,8 @@ static u16 iwlagn_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
        u16 size = (u16)sizeof(struct iwl_addsta_cmd);
        struct iwl_addsta_cmd *addsta = (struct iwl_addsta_cmd *)data;
        memcpy(addsta, cmd, size);
-       /* resrved in 5000 */
-       addsta->rate_n_flags = cpu_to_le16(0);
+       /* resrved in agn */
+       addsta->legacy_reserved = cpu_to_le16(0);
        return size;
 }
 
index a1a95d5f3923e7f93811b466f48a4411f81d2046..81754cddba73b4763a815d2fa03afff77f74a326 100644 (file)
@@ -91,7 +91,10 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv,
                tx_cmd->tid_tspec = qc[0] & 0xf;
                tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
        } else {
-               tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
+               if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
+                       tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
+               else
+                       tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
        }
 
        iwlagn_tx_cmd_protection(priv, info, fc, &tx_flags);
@@ -148,7 +151,7 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,
        if (ieee80211_is_data(fc)) {
                tx_cmd->initial_rate_index = 0;
                tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK;
-#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
+#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
                if (priv->tm_fixed_rate) {
                        /*
                         * rate overwrite by testmode
@@ -161,7 +164,8 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,
                }
 #endif
                return;
-       }
+       } else if (ieee80211_is_back_req(fc))
+               tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK;
 
        /**
         * If the current TX rate stored in mac80211 has the MCS bit set, it's
index daf010dad70ccebdc94ef4f03a15513d49fe66f2..f5fe42dbb3b0639001fb081fd2852515bc29ebc1 100644 (file)
@@ -366,7 +366,7 @@ static void iwl_continuous_event_trace(struct iwl_priv *priv)
        u32 num_wraps;  /* # times uCode wrapped to top of log */
        u32 next_entry; /* index of next entry to be written by uCode */
 
-       base = priv->device_pointers.error_event_table;
+       base = priv->shrd->device_pointers.error_event_table;
        if (iwlagn_hw_valid_rtc_data_addr(base)) {
                capacity = iwl_read_targ_mem(bus(priv), base);
                num_wraps = iwl_read_targ_mem(bus(priv),
@@ -1036,6 +1036,9 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
                priv->inst_evtlog_size =
                        priv->cfg->base_params->max_event_log_size;
        priv->inst_errlog_ptr = pieces.inst_errlog_ptr;
+#ifndef CONFIG_IWLWIFI_P2P
+       ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
+#endif
 
        priv->new_scan_threshold_behaviour =
                !!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWSCAN);
@@ -1057,7 +1060,6 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
                priv->sta_key_max_num = STA_KEY_MAX_NUM;
                priv->shrd->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
        }
-
        /*
         * figure out the offset of chain noise reset and gain commands
         * base on the size of standard phy calibration commands table size
@@ -1575,7 +1577,7 @@ static int iwl_init_drv(struct iwl_priv *priv)
 
        mutex_init(&priv->shrd->mutex);
 
-       INIT_LIST_HEAD(&priv->calib_results);
+       INIT_LIST_HEAD(&trans(priv)->calib_results);
 
        priv->ieee_channels = NULL;
        priv->ieee_rates = NULL;
@@ -1633,7 +1635,6 @@ err:
 
 static void iwl_uninit_drv(struct iwl_priv *priv)
 {
-       iwl_calib_free_results(priv);
        iwl_free_geos(priv);
        iwl_free_channel_map(priv);
        if (priv->tx_cmd_pool)
@@ -1703,8 +1704,14 @@ static void iwl_debug_config(struct iwl_priv *priv)
                "disabled\n");
 #endif
 
-       dev_printk(KERN_INFO, bus(priv)->dev, "CONFIG_IWLWIFI_DEVICE_SVTOOL "
-#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
+       dev_printk(KERN_INFO, bus(priv)->dev, "CONFIG_IWLWIFI_DEVICE_TESTMODE "
+#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
+               "enabled\n");
+#else
+               "disabled\n");
+#endif
+       dev_printk(KERN_INFO, bus(priv)->dev, "CONFIG_IWLWIFI_P2P "
+#ifdef CONFIG_IWLWIFI_P2P
                "enabled\n");
 #else
                "disabled\n");
@@ -1814,11 +1821,11 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
                goto out_free_eeprom;
 
        /* extract MAC Address */
-       iwl_eeprom_get_mac(priv, priv->addresses[0].addr);
+       iwl_eeprom_get_mac(priv->shrd, priv->addresses[0].addr);
        IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->addresses[0].addr);
        priv->hw->wiphy->addresses = priv->addresses;
        priv->hw->wiphy->n_addresses = 1;
-       num_mac = iwl_eeprom_query16(priv, EEPROM_NUM_MAC_ADDRESS);
+       num_mac = iwl_eeprom_query16(priv->shrd, EEPROM_NUM_MAC_ADDRESS);
        if (num_mac > 1) {
                memcpy(priv->addresses[1].addr, priv->addresses[0].addr,
                       ETH_ALEN);
@@ -1883,7 +1890,7 @@ out_destroy_workqueue:
        priv->shrd->workqueue = NULL;
        iwl_uninit_drv(priv);
 out_free_eeprom:
-       iwl_eeprom_free(priv);
+       iwl_eeprom_free(priv->shrd);
 out_free_trans:
        iwl_trans_free(trans(priv));
 out_free_traffic_mem:
@@ -1922,7 +1929,7 @@ void __devexit iwl_remove(struct iwl_priv * priv)
 
        iwl_dealloc_ucode(trans(priv));
 
-       iwl_eeprom_free(priv);
+       iwl_eeprom_free(priv->shrd);
 
        /*netif_stop_queue(dev); */
        flush_workqueue(priv->shrd->workqueue);
index f2f10702754d1f467da6f6a3514eaf305bda13b6..eb453ea41c41e05b44ad45deae8cc82c06ba6f93 100644 (file)
@@ -117,7 +117,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
 /* lib */
 int iwlagn_send_tx_power(struct iwl_priv *priv);
 void iwlagn_temperature(struct iwl_priv *priv);
-u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv);
+u16 iwl_eeprom_calib_version(struct iwl_shared *shrd);
 int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control);
 void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control);
 int iwlagn_send_beacon_cmd(struct iwl_priv *priv);
@@ -354,12 +354,12 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags)
 
 /* eeprom */
 void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv);
-void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac);
+void iwl_eeprom_get_mac(const struct iwl_shared *shrd, u8 *mac);
 
 extern int iwlagn_init_alive_start(struct iwl_priv *priv);
 extern int iwl_alive_start(struct iwl_priv *priv);
 /* svtool */
-#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
+#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
 extern int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data,
                                   int len);
 extern int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw,
index f4eccf583775f0b4b806d6b3ab2de7d220dedd61..265de39d394ca9ce7093b37f007e0fb2c3c94a85 100644 (file)
@@ -109,10 +109,10 @@ enum {
        /* RX, TX, LEDs */
        REPLY_TX = 0x1c,
        REPLY_LEDS_CMD = 0x48,
-       REPLY_TX_LINK_QUALITY_CMD = 0x4e, /* for 4965 and up */
+       REPLY_TX_LINK_QUALITY_CMD = 0x4e,
 
        /* WiMAX coexistence */
-       COEX_PRIORITY_TABLE_CMD = 0x5a, /* for 5000 series and up */
+       COEX_PRIORITY_TABLE_CMD = 0x5a,
        COEX_MEDIUM_NOTIFICATION = 0x5b,
        COEX_EVENT_CMD = 0x5c,
 
@@ -466,23 +466,27 @@ struct iwl_error_event_table {
        u32 frame_ptr;          /* frame pointer */
        u32 stack_ptr;          /* stack pointer */
        u32 hcmd;               /* last host command header */
-#if 0
-       /* no need to read the remainder, we don't use the values */
-       u32 isr0;               /* isr status register LMPM_NIC_ISR0: rxtx_flag */
-       u32 isr1;               /* isr status register LMPM_NIC_ISR1: host_flag */
-       u32 isr2;               /* isr status register LMPM_NIC_ISR2: enc_flag */
-       u32 isr3;               /* isr status register LMPM_NIC_ISR3: time_flag */
-       u32 isr4;               /* isr status register LMPM_NIC_ISR4: wico interrupt */
+       u32 isr0;               /* isr status register LMPM_NIC_ISR0:
+                                * rxtx_flag */
+       u32 isr1;               /* isr status register LMPM_NIC_ISR1:
+                                * host_flag */
+       u32 isr2;               /* isr status register LMPM_NIC_ISR2:
+                                * enc_flag */
+       u32 isr3;               /* isr status register LMPM_NIC_ISR3:
+                                * time_flag */
+       u32 isr4;               /* isr status register LMPM_NIC_ISR4:
+                                * wico interrupt */
        u32 isr_pref;           /* isr status register LMPM_NIC_PREF_STAT */
        u32 wait_event;         /* wait event() caller address */
        u32 l2p_control;        /* L2pControlField */
        u32 l2p_duration;       /* L2pDurationField */
        u32 l2p_mhvalid;        /* L2pMhValidBits */
        u32 l2p_addr_match;     /* L2pAddrMatchStat */
-       u32 lmpm_pmg_sel;       /* indicate which clocks are turned on (LMPM_PMG_SEL) */
-       u32 u_timestamp;        /* indicate when the date and time of the compilation */
+       u32 lmpm_pmg_sel;       /* indicate which clocks are turned on
+                                * (LMPM_PMG_SEL) */
+       u32 u_timestamp;        /* indicate when the date and time of the
+                                * compilation */
        u32 flow_handler;       /* FH read/write pointers, RX credit */
-#endif
 } __packed;
 
 struct iwl_alive_resp {
@@ -810,7 +814,7 @@ struct iwl_qosparam_cmd {
 #define        IWLAGN_STATION_COUNT    16
 
 #define        IWL_INVALID_STATION     255
-#define IWL_MAX_TID_COUNT      9
+#define IWL_MAX_TID_COUNT      8
 
 #define STA_FLG_TX_RATE_MSK            cpu_to_le32(1 << 2)
 #define STA_FLG_PWR_SAVE_MSK           cpu_to_le32(1 << 8)
@@ -931,8 +935,7 @@ struct iwl_addsta_cmd {
         * corresponding to bit (e.g. bit 5 controls TID 5).
         * Set modify_mask bit STA_MODIFY_TID_DISABLE_TX to use this field. */
        __le16 tid_disable_tx;
-
-       __le16  rate_n_flags;           /* 3945 only */
+       __le16 legacy_reserved;
 
        /* TID for which to add block-ack support.
         * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */
@@ -1162,8 +1165,7 @@ struct iwl_rx_mpdu_res_start {
  *
  * uCode handles retrying Tx when an ACK is expected but not received.
  * This includes trying lower data rates than the one requested in the Tx
- * command, as set up by the REPLY_RATE_SCALE (for 3945) or
- * REPLY_TX_LINK_QUALITY_CMD (agn).
+ * command, as set up by the REPLY_TX_LINK_QUALITY_CMD (agn).
  *
  * Driver sets up transmit power for various rates via REPLY_TX_PWR_TABLE_CMD.
  * This command must be executed after every RXON command, before Tx can occur.
@@ -1175,25 +1177,9 @@ struct iwl_rx_mpdu_res_start {
  * 1: Use RTS/CTS protocol or CTS-to-self if spec allows it
  * before this frame. if CTS-to-self required check
  * RXON_FLG_SELF_CTS_EN status.
- * unused in 3945/4965, used in 5000 series and after
  */
 #define TX_CMD_FLG_PROT_REQUIRE_MSK cpu_to_le32(1 << 0)
 
-/*
- * 1: Use Request-To-Send protocol before this frame.
- * Mutually exclusive vs. TX_CMD_FLG_CTS_MSK.
- * used in 3945/4965, unused in 5000 series and after
- */
-#define TX_CMD_FLG_RTS_MSK cpu_to_le32(1 << 1)
-
-/*
- * 1: Transmit Clear-To-Send to self before this frame.
- * Driver should set this for AUTH/DEAUTH/ASSOC-REQ/REASSOC mgmnt frames.
- * Mutually exclusive vs. TX_CMD_FLG_RTS_MSK.
- * used in 3945/4965, unused in 5000 series and after
- */
-#define TX_CMD_FLG_CTS_MSK cpu_to_le32(1 << 2)
-
 /* 1: Expect ACK from receiving station
  * 0: Don't expect ACK (MAC header's duration field s/b 0)
  * Set this for unicast frames, but not broadcast/multicast. */
@@ -1211,18 +1197,8 @@ struct iwl_rx_mpdu_res_start {
  * Set when Txing a block-ack request frame.  Also set TX_CMD_FLG_ACK_MSK. */
 #define TX_CMD_FLG_IMM_BA_RSP_MASK  cpu_to_le32(1 << 6)
 
-/*
- * 1: Frame requires full Tx-Op protection.
- * Set this if either RTS or CTS Tx Flag gets set.
- * used in 3945/4965, unused in 5000 series and after
- */
-#define TX_CMD_FLG_FULL_TXOP_PROT_MSK cpu_to_le32(1 << 7)
-
-/* Tx antenna selection field; used only for 3945, reserved (0) for agn devices.
- * Set field to "0" to allow 3945 uCode to select antenna (normal usage). */
+/* Tx antenna selection field; reserved (0) for agn devices. */
 #define TX_CMD_FLG_ANT_SEL_MSK cpu_to_le32(0xf00)
-#define TX_CMD_FLG_ANT_A_MSK cpu_to_le32(1 << 8)
-#define TX_CMD_FLG_ANT_B_MSK cpu_to_le32(1 << 9)
 
 /* 1: Ignore Bluetooth priority for this frame.
  * 0: Delay Tx until Bluetooth device is done (normal usage). */
@@ -1568,7 +1544,6 @@ struct iwl_compressed_ba_resp {
        __le64 bitmap;
        __le16 scd_flow;
        __le16 scd_ssn;
-       /* following only for 5000 series and up */
        u8 txed;        /* number of frames sent */
        u8 txed_2_done; /* number of frames acked */
 } __packed;
@@ -1670,7 +1645,7 @@ struct iwl_link_qual_agg_params {
 /*
  * REPLY_TX_LINK_QUALITY_CMD = 0x4e (command, has simple generic response)
  *
- * For agn devices only; 3945 uses REPLY_RATE_SCALE.
+ * For agn devices
  *
  * Each station in the agn device's internal station table has its own table
  * of 16
@@ -1919,7 +1894,7 @@ struct iwl_link_quality_cmd {
 /*
  * REPLY_BT_CONFIG = 0x9b (command, has simple generic response)
  *
- * 3945 and agn devices support hardware handshake with Bluetooth device on
+ * agn devices support hardware handshake with Bluetooth device on
  * same platform.  Bluetooth device alerts wireless device when it will Tx;
  * wireless device can delay or kill its own Tx to accommodate.
  */
@@ -2203,8 +2178,8 @@ struct iwl_spectrum_notification {
 
 struct iwl_powertable_cmd {
        __le16 flags;
-       u8 keep_alive_seconds;          /* 3945 reserved */
-       u8 debug_flags;                 /* 3945 reserved */
+       u8 keep_alive_seconds;
+       u8 debug_flags;
        __le32 rx_data_timeout;
        __le32 tx_data_timeout;
        __le32 sleep_interval[IWL_POWER_VEC_SIZE];
@@ -2325,9 +2300,9 @@ struct iwl_scan_channel {
 /**
  * struct iwl_ssid_ie - directed scan network information element
  *
- * Up to 20 of these may appear in REPLY_SCAN_CMD (Note: Only 4 are in
- * 3945 SCAN api), selected by "type" bit field in struct iwl_scan_channel;
- * each channel may select different ssids from among the 20 (4) entries.
+ * Up to 20 of these may appear in REPLY_SCAN_CMD,
+ * selected by "type" bit field in struct iwl_scan_channel;
+ * each channel may select different ssids from among the 20 entries.
  * SSID IEs get transmitted in reverse order of entry.
  */
 struct iwl_ssid_ie {
@@ -2336,7 +2311,6 @@ struct iwl_ssid_ie {
        u8 ssid[32];
 } __packed;
 
-#define PROBE_OPTION_MAX_3945          4
 #define PROBE_OPTION_MAX               20
 #define TX_CMD_LIFE_TIME_INFINITE      cpu_to_le32(0xFFFFFFFF)
 #define IWL_GOOD_CRC_TH_DISABLED       0
@@ -2417,8 +2391,6 @@ struct iwl_scan_cmd {
                                 * channel */
        __le32 suspend_time;    /* pause scan this long (in "extended beacon
                                 * format") when returning to service chnl:
-                                * 3945; 31:24 # beacons, 19:0 additional usec,
-                                * 4965; 31:22 # beacons, 21:0 additional usec.
                                 */
        __le32 flags;           /* RXON_FLG_* */
        __le32 filter_flags;    /* RXON_FILTER_* */
@@ -2734,7 +2706,7 @@ struct statistics_div {
 
 struct statistics_general_common {
        __le32 temperature;   /* radio temperature */
-       __le32 temperature_m; /* for 5000 and up, this is radio voltage */
+       __le32 temperature_m; /* radio voltage */
        struct statistics_dbg dbg;
        __le32 sleep_time;
        __le32 slots_out;
index ccbcab40e78fcf480e90c0a43744c900c5ce1203..6bf6845e1a51f4cec02a8cda17688d866fdf80fb 100644 (file)
@@ -416,7 +416,7 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file,
                return -ENODATA;
        }
 
-       ptr = priv->eeprom;
+       ptr = priv->shrd->eeprom;
        if (!ptr) {
                IWL_ERR(priv, "Invalid EEPROM/OTP memory\n");
                return -ENOMEM;
@@ -428,7 +428,7 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file,
                IWL_ERR(priv, "Can not allocate Buffer\n");
                return -ENOMEM;
        }
-       eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
+       eeprom_ver = iwl_eeprom_query16(priv->shrd, EEPROM_VERSION);
        pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s, "
                        "version: 0x%x\n",
                        (trans(priv)->nvm_device_type == NVM_DEVICE_TYPE_OTP)
index 6f6a647d34f6003149fc7daddcbae4972a71b91c..69ecf6e2e658ae1c0e777d4b5f36faf185c8148b 100644 (file)
@@ -60,11 +60,10 @@ struct iwl_tx_queue;
 
 /* Default noise level to report when noise measurement is not available.
  *   This may be because we're:
- *   1)  Not associated (4965, no beacon statistics being sent to driver)
+ *   1)  Not associated  no beacon statistics being sent to driver)
  *   2)  Scanning (noise measurement does not apply to associated channel)
- *   3)  Receiving CCK (3945 delivers noise info only for OFDM frames)
  * Use default noise value of -127 ... this is below the range of measurable
- *   Rx dBm for either 3945 or 4965, so it can indicate "unmeasurable" to user.
+ *   Rx dBm for all agn devices, so it can indicate "unmeasurable" to user.
  *   Also, -127 works better than 0 when averaging frames with/without
  *   noise info (e.g. averaging might be done in app); measured dBm values are
  *   always negative ... using a negative value as the default keeps all
@@ -441,15 +440,6 @@ enum iwlagn_chain_noise_state {
        IWL_CHAIN_NOISE_DONE,
 };
 
-
-/* Opaque calibration results */
-struct iwl_calib_result {
-       struct list_head list;
-       size_t cmd_len;
-       struct iwl_calib_hdr hdr;
-       /* data follows */
-};
-
 /* Sensitivity calib data */
 struct iwl_sensitivity_data {
        u32 auto_corr_ofdm;
@@ -751,7 +741,7 @@ enum iwl_scan_type {
        IWL_SCAN_ROC,
 };
 
-#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
+#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
 struct iwl_testmode_trace {
        u32 buff_size;
        u32 total_size;
@@ -831,9 +821,6 @@ struct iwl_priv {
        s32 temperature;        /* Celsius */
        s32 last_temperature;
 
-       /* init calibration results */
-       struct list_head calib_results;
-
        struct iwl_wipan_noa_data __rcu *noa_data;
 
        /* Scan related variables */
@@ -866,11 +853,6 @@ struct iwl_priv {
 
        __le16 switch_channel;
 
-       struct {
-               u32 error_event_table;
-               u32 log_event_table;
-       } device_pointers;
-
        u16 active_rate;
 
        u8 start_calib;
@@ -904,10 +886,6 @@ struct iwl_priv {
        /* Indication if ieee80211_ops->open has been called */
        u8 is_open;
 
-       /* eeprom -- this is in the card's little endian byte order */
-       u8 *eeprom;
-       struct iwl_eeprom_calib_info *calib_info;
-
        enum nl80211_iftype iw_mode;
 
        /* Last Rx'd beacon timestamp */
@@ -1040,7 +1018,7 @@ struct iwl_priv {
        struct led_classdev led;
        unsigned long blink_on, blink_off;
        bool led_registered;
-#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
+#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
        struct iwl_testmode_trace testmode_trace;
        struct iwl_testmode_sram testmode_sram;
        u32 tm_fixed_rate;
index dcada0827ea43db482effeaa8966b62af51be67e..6fcc7d586b248592e5526df606aceeaf8a2ab3dc 100644 (file)
@@ -215,11 +215,11 @@ static int iwl_eeprom_verify_signature(struct iwl_trans *trans)
        return ret;
 }
 
-u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset)
+u16 iwl_eeprom_query16(const struct iwl_shared *shrd, size_t offset)
 {
-       if (!priv->eeprom)
+       if (!shrd->eeprom)
                return 0;
-       return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8);
+       return (u16)shrd->eeprom[offset] | ((u16)shrd->eeprom[offset + 1] << 8);
 }
 
 int iwl_eeprom_check_version(struct iwl_priv *priv)
@@ -227,8 +227,8 @@ int iwl_eeprom_check_version(struct iwl_priv *priv)
        u16 eeprom_ver;
        u16 calib_ver;
 
-       eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
-       calib_ver = iwlagn_eeprom_calib_version(priv);
+       eeprom_ver = iwl_eeprom_query16(priv->shrd, EEPROM_VERSION);
+       calib_ver = iwl_eeprom_calib_version(priv->shrd);
 
        if (eeprom_ver < priv->cfg->eeprom_ver ||
            calib_ver < priv->cfg->eeprom_calib_ver)
@@ -249,11 +249,12 @@ err:
 
 int iwl_eeprom_check_sku(struct iwl_priv *priv)
 {
+       struct iwl_shared *shrd = priv->shrd;
        u16 radio_cfg;
 
        if (!priv->cfg->sku) {
                /* not using sku overwrite */
-               priv->cfg->sku = iwl_eeprom_query16(priv, EEPROM_SKU_CAP);
+               priv->cfg->sku = iwl_eeprom_query16(shrd, EEPROM_SKU_CAP);
                if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE &&
                    !priv->cfg->ht_params) {
                        IWL_ERR(priv, "Invalid 11n configuration\n");
@@ -269,7 +270,7 @@ int iwl_eeprom_check_sku(struct iwl_priv *priv)
 
        if (!priv->cfg->valid_tx_ant && !priv->cfg->valid_rx_ant) {
                /* not using .cfg overwrite */
-               radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
+               radio_cfg = iwl_eeprom_query16(shrd, EEPROM_RADIO_CONFIG);
                priv->cfg->valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg);
                priv->cfg->valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(radio_cfg);
                if (!priv->cfg->valid_tx_ant || !priv->cfg->valid_rx_ant) {
@@ -289,9 +290,9 @@ int iwl_eeprom_check_sku(struct iwl_priv *priv)
        return 0;
 }
 
-void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac)
+void iwl_eeprom_get_mac(const struct iwl_shared *shrd, u8 *mac)
 {
-       const u8 *addr = iwl_eeprom_query_addr(priv,
+       const u8 *addr = iwl_eeprom_query_addr(shrd,
                                        EEPROM_MAC_ADDRESS);
        memcpy(mac, addr, ETH_ALEN);
 }
@@ -582,6 +583,7 @@ iwl_eeprom_enh_txp_read_element(struct iwl_priv *priv,
 
 void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv)
 {
+       struct iwl_shared *shrd = priv->shrd;
        struct iwl_eeprom_enhanced_txpwr *txp_array, *txp;
        int idx, entries;
        __le16 *txp_len;
@@ -590,10 +592,10 @@ void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv)
        BUILD_BUG_ON(sizeof(struct iwl_eeprom_enhanced_txpwr) != 8);
 
        /* the length is in 16-bit words, but we want entries */
-       txp_len = (__le16 *) iwl_eeprom_query_addr(priv, EEPROM_TXP_SZ_OFFS);
+       txp_len = (__le16 *) iwl_eeprom_query_addr(shrd, EEPROM_TXP_SZ_OFFS);
        entries = le16_to_cpup(txp_len) * 2 / EEPROM_TXP_ENTRY_LEN;
 
-       txp_array = (void *) iwl_eeprom_query_addr(priv, EEPROM_TXP_OFFS);
+       txp_array = (void *) iwl_eeprom_query_addr(shrd, EEPROM_TXP_OFFS);
 
        for (idx = 0; idx < entries; idx++) {
                txp = &txp_array[idx];
@@ -646,12 +648,13 @@ void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv)
 /**
  * iwl_eeprom_init - read EEPROM contents
  *
- * Load the EEPROM contents from adapter into priv->eeprom
+ * Load the EEPROM contents from adapter into shrd->eeprom
  *
  * NOTE:  This routine uses the non-debug IO access functions.
  */
 int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
 {
+       struct iwl_shared *shrd = priv->shrd;
        __le16 *e;
        u32 gp = iwl_read32(bus(priv), CSR_EEPROM_GP);
        int sz;
@@ -666,12 +669,12 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
        /* allocate eeprom */
        sz = priv->cfg->base_params->eeprom_size;
        IWL_DEBUG_EEPROM(priv, "NVM size = %d\n", sz);
-       priv->eeprom = kzalloc(sz, GFP_KERNEL);
-       if (!priv->eeprom) {
+       shrd->eeprom = kzalloc(sz, GFP_KERNEL);
+       if (!shrd->eeprom) {
                ret = -ENOMEM;
                goto alloc_err;
        }
-       e = (__le16 *)priv->eeprom;
+       e = (__le16 *)shrd->eeprom;
 
        iwl_apm_init(priv);
 
@@ -746,7 +749,7 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
        IWL_DEBUG_EEPROM(priv, "NVM Type: %s, version: 0x%x\n",
                       (trans(priv)->nvm_device_type == NVM_DEVICE_TYPE_OTP)
                       ? "OTP" : "EEPROM",
-                      iwl_eeprom_query16(priv, EEPROM_VERSION));
+                      iwl_eeprom_query16(shrd, EEPROM_VERSION));
 
        ret = 0;
 done:
@@ -754,17 +757,17 @@ done:
 
 err:
        if (ret)
-               iwl_eeprom_free(priv);
+               iwl_eeprom_free(priv->shrd);
        /* Reset chip to save power until we load uCode during "up". */
        iwl_apm_stop(priv);
 alloc_err:
        return ret;
 }
 
-void iwl_eeprom_free(struct iwl_priv *priv)
+void iwl_eeprom_free(struct iwl_shared *shrd)
 {
-       kfree(priv->eeprom);
-       priv->eeprom = NULL;
+       kfree(shrd->eeprom);
+       shrd->eeprom = NULL;
 }
 
 static void iwl_init_band_reference(const struct iwl_priv *priv,
@@ -772,49 +775,50 @@ static void iwl_init_band_reference(const struct iwl_priv *priv,
                        const struct iwl_eeprom_channel **eeprom_ch_info,
                        const u8 **eeprom_ch_index)
 {
+       struct iwl_shared *shrd = priv->shrd;
        u32 offset = priv->cfg->lib->
                        eeprom_ops.regulatory_bands[eep_band - 1];
        switch (eep_band) {
        case 1:         /* 2.4GHz band */
                *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_1);
                *eeprom_ch_info = (struct iwl_eeprom_channel *)
-                               iwl_eeprom_query_addr(priv, offset);
+                               iwl_eeprom_query_addr(shrd, offset);
                *eeprom_ch_index = iwl_eeprom_band_1;
                break;
        case 2:         /* 4.9GHz band */
                *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_2);
                *eeprom_ch_info = (struct iwl_eeprom_channel *)
-                               iwl_eeprom_query_addr(priv, offset);
+                               iwl_eeprom_query_addr(shrd, offset);
                *eeprom_ch_index = iwl_eeprom_band_2;
                break;
        case 3:         /* 5.2GHz band */
                *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_3);
                *eeprom_ch_info = (struct iwl_eeprom_channel *)
-                               iwl_eeprom_query_addr(priv, offset);
+                               iwl_eeprom_query_addr(shrd, offset);
                *eeprom_ch_index = iwl_eeprom_band_3;
                break;
        case 4:         /* 5.5GHz band */
                *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_4);
                *eeprom_ch_info = (struct iwl_eeprom_channel *)
-                               iwl_eeprom_query_addr(priv, offset);
+                               iwl_eeprom_query_addr(shrd, offset);
                *eeprom_ch_index = iwl_eeprom_band_4;
                break;
        case 5:         /* 5.7GHz band */
                *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_5);
                *eeprom_ch_info = (struct iwl_eeprom_channel *)
-                               iwl_eeprom_query_addr(priv, offset);
+                               iwl_eeprom_query_addr(shrd, offset);
                *eeprom_ch_index = iwl_eeprom_band_5;
                break;
        case 6:         /* 2.4GHz ht40 channels */
                *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_6);
                *eeprom_ch_info = (struct iwl_eeprom_channel *)
-                               iwl_eeprom_query_addr(priv, offset);
+                               iwl_eeprom_query_addr(shrd, offset);
                *eeprom_ch_index = iwl_eeprom_band_6;
                break;
        case 7:         /* 5 GHz ht40 channels */
                *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_7);
                *eeprom_ch_info = (struct iwl_eeprom_channel *)
-                               iwl_eeprom_query_addr(priv, offset);
+                               iwl_eeprom_query_addr(shrd, offset);
                *eeprom_ch_index = iwl_eeprom_band_7;
                break;
        default:
@@ -1064,7 +1068,7 @@ void iwl_rf_config(struct iwl_priv *priv)
 {
        u16 radio_cfg;
 
-       radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
+       radio_cfg = iwl_eeprom_query16(priv->shrd, EEPROM_RADIO_CONFIG);
 
        /* write radio config values to register */
        if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX) {
index c94747e7299e234a77b71b27af47cf73ae235495..9fa937ec35e38ca314284453ebad05de058c505e 100644 (file)
@@ -66,6 +66,7 @@
 #include <net/mac80211.h>
 
 struct iwl_priv;
+struct iwl_shared;
 
 /*
  * EEPROM access time values:
@@ -305,11 +306,11 @@ struct iwl_eeprom_ops {
 
 
 int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev);
-void iwl_eeprom_free(struct iwl_priv *priv);
+void iwl_eeprom_free(struct iwl_shared *shrd);
 int  iwl_eeprom_check_version(struct iwl_priv *priv);
 int  iwl_eeprom_check_sku(struct iwl_priv *priv);
-const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset);
-u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset);
+const u8 *iwl_eeprom_query_addr(const struct iwl_shared *shrd, size_t offset);
+u16 iwl_eeprom_query16(const struct iwl_shared *shrd, size_t offset);
 int iwl_init_channel_map(struct iwl_priv *priv);
 void iwl_free_channel_map(struct iwl_priv *priv);
 const struct iwl_channel_info *iwl_get_channel_info(
index 55308b88faac73cbb68c18eff65202e742c2d770..e3944f4e4fd622cada27c13b66278db2ee540120 100644 (file)
@@ -427,7 +427,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
        iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_CLR,
                          CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
 
-       base = priv->device_pointers.error_event_table;
+       base = priv->shrd->device_pointers.error_event_table;
        if (iwlagn_hw_valid_rtc_data_addr(base)) {
                spin_lock_irqsave(&bus(priv)->reg_lock, flags);
                ret = iwl_grab_nic_access_silent(bus(priv));
@@ -811,21 +811,9 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
 
        /* 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
+       if (ctx->ht.enabled)
+               iwlagn_config_ht40(conf, ctx);
+       else
                ctx->ht.is_40mhz = false;
 
        if ((le16_to_cpu(ctx->staging.channel) != ch))
@@ -1060,6 +1048,9 @@ static int iwlagn_mac_tx_sync(struct ieee80211_hw *hw,
        int ret;
        u8 sta_id;
 
+       if (ctx->ctxid != IWL_RXON_CTX_PAN)
+               return 0;
+
        IWL_DEBUG_MAC80211(priv, "enter\n");
        mutex_lock(&priv->shrd->mutex);
 
@@ -1109,6 +1100,9 @@ static void iwlagn_mac_finish_tx_sync(struct ieee80211_hw *hw,
        struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
        struct iwl_rxon_context *ctx = vif_priv->ctx;
 
+       if (ctx->ctxid != IWL_RXON_CTX_PAN)
+               return;
+
        IWL_DEBUG_MAC80211(priv, "enter\n");
        mutex_lock(&priv->shrd->mutex);
 
index 39aa9cf5b847353fa2542ad30f8c8a829c668eef..29a7284aa3ef9ff60cb0c9154f70f1b583b39538 100644 (file)
@@ -97,6 +97,7 @@
 struct iwl_cfg;
 struct iwl_bus;
 struct iwl_priv;
+struct iwl_trans;
 struct iwl_sensitivity_ranges;
 struct iwl_trans_ops;
 
@@ -294,7 +295,7 @@ enum iwl_ucode_type {
 struct iwl_notification_wait {
        struct list_head list;
 
-       void (*fn)(struct iwl_priv *priv, struct iwl_rx_packet *pkt,
+       void (*fn)(struct iwl_trans *trans, struct iwl_rx_packet *pkt,
                   void *data);
        void *fn_data;
 
@@ -323,6 +324,7 @@ struct iwl_notification_wait {
  * @notif_waits: things waiting for notification
  * @notif_wait_lock: lock protecting notification
  * @notif_waitq: head of notification wait queue
+ * @device_pointers: pointers to ucode event tables
  */
 struct iwl_shared {
 #ifdef CONFIG_IWLWIFI_DEBUG
@@ -351,6 +353,9 @@ struct iwl_shared {
 
        wait_queue_head_t wait_command_queue;
 
+       /* eeprom -- this is in the card's little endian byte order */
+       u8 *eeprom;
+
        /* ucode related variables */
        enum iwl_ucode_type ucode_type;
 
@@ -358,6 +363,12 @@ struct iwl_shared {
        struct list_head notif_waits;
        spinlock_t notif_wait_lock;
        wait_queue_head_t notif_waitq;
+
+       struct {
+               u32 error_event_table;
+               u32 log_event_table;
+       } device_pointers;
+
 };
 
 /*Whatever _m is (iwl_trans, iwl_priv, iwl_bus, these macros will work */
@@ -507,7 +518,7 @@ void __acquires(wait_entry)
 iwl_init_notification_wait(struct iwl_shared *shrd,
                              struct iwl_notification_wait *wait_entry,
                              u8 cmd,
-                             void (*fn)(struct iwl_priv *priv,
+                             void (*fn)(struct iwl_trans *trans,
                                         struct iwl_rx_packet *pkt,
                                         void *data),
                              void *fn_data);
index ff72dbcfd52d66dbd73714e1b982c072eaea0741..a874eb7b5f8e3e0920aec32e416f9d26e83d102b 100644 (file)
@@ -77,6 +77,7 @@
 #include "iwl-agn.h"
 #include "iwl-testmode.h"
 #include "iwl-trans.h"
+#include "iwl-bus.h"
 
 /* The TLVs used in the gnl message policy between the kernel module and
  * user space application. iwl_testmode_gnl_msg_policy is to be carried
@@ -110,6 +111,9 @@ struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = {
        [IWL_TM_ATTR_SRAM_ADDR] = { .type = NLA_U32, },
        [IWL_TM_ATTR_SRAM_SIZE] = { .type = NLA_U32, },
        [IWL_TM_ATTR_SRAM_DUMP] = { .type = NLA_UNSPEC, },
+
+       [IWL_TM_ATTR_FW_VERSION] = { .type = NLA_U32, },
+       [IWL_TM_ATTR_DEVICE_ID] = { .type = NLA_U32, },
 };
 
 /*
@@ -416,6 +420,8 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
        struct sk_buff *skb;
        unsigned char *rsp_data_ptr = NULL;
        int status = 0, rsp_data_len = 0;
+       char buf[32], *ptr = NULL;
+       unsigned int num, devid;
 
        switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
        case IWL_TM_CMD_APP2DEV_GET_DEVICENAME:
@@ -479,7 +485,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
                break;
 
        case IWL_TM_CMD_APP2DEV_GET_EEPROM:
-               if (priv->eeprom) {
+               if (priv->shrd->eeprom) {
                        skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
                                priv->cfg->base_params->eeprom_size + 20);
                        if (!skb) {
@@ -491,7 +497,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
                                IWL_TM_CMD_DEV2APP_EEPROM_RSP);
                        NLA_PUT(skb, IWL_TM_ATTR_EEPROM,
                                priv->cfg->base_params->eeprom_size,
-                               priv->eeprom);
+                               priv->shrd->eeprom);
                        status = cfg80211_testmode_reply(skb);
                        if (status < 0)
                                IWL_DEBUG_INFO(priv,
@@ -510,6 +516,43 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
                priv->tm_fixed_rate = nla_get_u32(tb[IWL_TM_ATTR_FIXRATE]);
                break;
 
+       case IWL_TM_CMD_APP2DEV_GET_FW_VERSION:
+               IWL_INFO(priv, "uCode version raw: 0x%x\n", priv->ucode_ver);
+
+               skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20);
+               if (!skb) {
+                       IWL_DEBUG_INFO(priv, "Error allocating memory\n");
+                       return -ENOMEM;
+               }
+               NLA_PUT_U32(skb, IWL_TM_ATTR_FW_VERSION, priv->ucode_ver);
+               status = cfg80211_testmode_reply(skb);
+               if (status < 0)
+                       IWL_DEBUG_INFO(priv,
+                                       "Error sending msg : %d\n", status);
+               break;
+
+       case IWL_TM_CMD_APP2DEV_GET_DEVICE_ID:
+               bus_get_hw_id(bus(priv), buf, sizeof(buf));
+               ptr = buf;
+               strsep(&ptr, ":");
+               sscanf(strsep(&ptr, ":"), "%x", &num);
+               sscanf(strsep(&ptr, ":"), "%x", &devid);
+               IWL_INFO(priv, "Device ID = 0x%04x, SubDevice ID= 0x%04x\n",
+                               num, devid);
+               devid |= (num << 16);
+
+               skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20);
+               if (!skb) {
+                       IWL_DEBUG_INFO(priv, "Error allocating memory\n");
+                       return -ENOMEM;
+               }
+               NLA_PUT_U32(skb, IWL_TM_ATTR_DEVICE_ID, devid);
+               status = cfg80211_testmode_reply(skb);
+               if (status < 0)
+                       IWL_DEBUG_INFO(priv,
+                                       "Error sending msg : %d\n", status);
+               break;
+
        default:
                IWL_DEBUG_INFO(priv, "Unknown testmode driver command ID\n");
                return -ENOSYS;
@@ -842,6 +885,8 @@ int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
        case IWL_TM_CMD_APP2DEV_GET_EEPROM:
        case IWL_TM_CMD_APP2DEV_FIXRATE_REQ:
        case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW:
+       case IWL_TM_CMD_APP2DEV_GET_FW_VERSION:
+       case IWL_TM_CMD_APP2DEV_GET_DEVICE_ID:
                IWL_DEBUG_INFO(priv, "testmode cmd to driver\n");
                result = iwl_testmode_driver(hw, tb);
                break;
index deedd27c5f3d7a0a418fa5624a97e762098df661..26138f110340819fc68407d21e3a827cce101591 100644 (file)
  *     commands from user applicaiton to read data in sram
  *
  * @IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW: load Weak On Wireless LAN uCode image
+ * @IWL_TM_CMD_APP2DEV_GET_FW_VERSION: retrieve uCode version
+ * @IWL_TM_CMD_APP2DEV_GET_DEVICE_ID: retrieve ID information in device
  *
  */
 enum iwl_tm_cmd_t {
@@ -143,7 +145,9 @@ enum iwl_tm_cmd_t {
        IWL_TM_CMD_APP2DEV_READ_SRAM            = 20,
        IWL_TM_CMD_APP2DEV_DUMP_SRAM            = 21,
        IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW       = 22,
-       IWL_TM_CMD_MAX                          = 23,
+       IWL_TM_CMD_APP2DEV_GET_FW_VERSION       = 23,
+       IWL_TM_CMD_APP2DEV_GET_DEVICE_ID        = 24,
+       IWL_TM_CMD_MAX                          = 25,
 };
 
 /*
@@ -225,6 +229,14 @@ enum iwl_tm_cmd_t {
  *     When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_DUMP_SRAM,
  *     IWL_TM_ATTR_SRAM_DUMP for the data in sram
  *
+ * @IWL_TM_ATTR_FW_VERSION:
+ *     When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_GET_FW_VERSION,
+ *     IWL_TM_ATTR_FW_VERSION for the uCode version
+ *
+ * @IWL_TM_ATTR_DEVICE_ID:
+ *     When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_GET_DEVICE_ID,
+ *     IWL_TM_ATTR_DEVICE_ID for the device ID information
+ *
  */
 enum iwl_tm_attr_t {
        IWL_TM_ATTR_NOT_APPLICABLE              = 0,
@@ -245,7 +257,9 @@ enum iwl_tm_attr_t {
        IWL_TM_ATTR_SRAM_ADDR                   = 15,
        IWL_TM_ATTR_SRAM_SIZE                   = 16,
        IWL_TM_ATTR_SRAM_DUMP                   = 17,
-       IWL_TM_ATTR_MAX                         = 18,
+       IWL_TM_ATTR_FW_VERSION                  = 18,
+       IWL_TM_ATTR_DEVICE_ID                   = 19,
+       IWL_TM_ATTR_MAX                         = 20,
 };
 
 /* uCode trace buffer */
index becd92173ddd3505feb060752ab0ae2cb4269f22..2ee00e0f39d346e6f71287d5b4ffc057ff3de676 100644 (file)
@@ -594,7 +594,7 @@ static void iwl_dump_nic_error_log(struct iwl_trans *trans)
        struct iwl_trans_pcie *trans_pcie =
                IWL_TRANS_GET_PCIE_TRANS(trans);
 
-       base = priv->device_pointers.error_event_table;
+       base = trans->shrd->device_pointers.error_event_table;
        if (trans->shrd->ucode_type == IWL_UCODE_INIT) {
                if (!base)
                        base = priv->init_errlog_ptr;
@@ -648,6 +648,21 @@ static void iwl_dump_nic_error_log(struct iwl_trans *trans)
        IWL_ERR(trans, "0x%08X | hw version\n", table.hw_ver);
        IWL_ERR(trans, "0x%08X | board version\n", table.brd_ver);
        IWL_ERR(trans, "0x%08X | hcmd\n", table.hcmd);
+
+       IWL_ERR(trans, "0x%08X | isr0\n", table.isr0);
+       IWL_ERR(trans, "0x%08X | isr1\n", table.isr1);
+       IWL_ERR(trans, "0x%08X | isr2\n", table.isr2);
+       IWL_ERR(trans, "0x%08X | isr3\n", table.isr3);
+       IWL_ERR(trans, "0x%08X | isr4\n", table.isr4);
+       IWL_ERR(trans, "0x%08X | isr_pref\n", table.isr_pref);
+       IWL_ERR(trans, "0x%08X | wait_event\n", table.wait_event);
+       IWL_ERR(trans, "0x%08X | l2p_control\n", table.l2p_control);
+       IWL_ERR(trans, "0x%08X | l2p_duration\n", table.l2p_duration);
+       IWL_ERR(trans, "0x%08X | l2p_mhvalid\n", table.l2p_mhvalid);
+       IWL_ERR(trans, "0x%08X | l2p_addr_match\n", table.l2p_addr_match);
+       IWL_ERR(trans, "0x%08X | lmpm_pmg_sel\n", table.lmpm_pmg_sel);
+       IWL_ERR(trans, "0x%08X | timestamp\n", table.u_timestamp);
+       IWL_ERR(trans, "0x%08X | flow_handler\n", table.flow_handler);
 }
 
 /**
@@ -709,7 +724,7 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
        if (num_events == 0)
                return pos;
 
-       base = priv->device_pointers.log_event_table;
+       base = trans->shrd->device_pointers.log_event_table;
        if (trans->shrd->ucode_type == IWL_UCODE_INIT) {
                if (!base)
                        base = priv->init_evtlog_ptr;
@@ -823,7 +838,7 @@ int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log,
        size_t bufsz = 0;
        struct iwl_priv *priv = priv(trans);
 
-       base = priv->device_pointers.log_event_table;
+       base = trans->shrd->device_pointers.log_event_table;
        if (trans->shrd->ucode_type == IWL_UCODE_INIT) {
                logsize = priv->init_evtlog_size;
                if (!base)
index 304b2ea0375c26d91d18d64f280560c877bf1089..66e1b9fa0b8b9bfa2079a1b70817413e1aab41f4 100644 (file)
@@ -1373,6 +1373,7 @@ static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid,
 
 static void iwl_trans_pcie_free(struct iwl_trans *trans)
 {
+       iwl_calib_free_results(trans);
        iwl_trans_pcie_tx_free(trans);
        iwl_trans_pcie_rx_free(trans);
        free_irq(bus(trans)->irq, trans);
index 4a29b8ab998ecc5a2d78582961b08b48522f9d4a..f94a6ee5f82f6693d866bab58d606652eae87112 100644 (file)
@@ -220,6 +220,14 @@ struct fw_img {
        struct fw_desc data;    /* firmware data image */
 };
 
+/* Opaque calibration results */
+struct iwl_calib_result {
+       struct list_head list;
+       size_t cmd_len;
+       struct iwl_calib_hdr hdr;
+       /* data follows */
+};
+
 /**
  * struct iwl_trans - transport common data
  * @ops - pointer to iwl_trans_ops
@@ -229,6 +237,8 @@ struct fw_img {
  * @ucode_rt: run time ucode image
  * @ucode_init: init ucode image
  * @ucode_wowlan: wake on wireless ucode image (optional)
+ * @nvm_device_type: indicates OTP or eeprom
+ * @calib_results: list head for init calibration results
  */
 struct iwl_trans {
        const struct iwl_trans_ops *ops;
@@ -243,6 +253,9 @@ struct iwl_trans {
        /* eeprom related variables */
        int    nvm_device_type;
 
+       /* init calibration results */
+       struct list_head calib_results;
+
        /* pointer to trans specific struct */
        /*Ensure that this pointer will always be aligned to sizeof pointer */
        char trans_specific[0] __attribute__((__aligned__(sizeof(void *))));
@@ -379,4 +392,9 @@ int iwl_alloc_fw_desc(struct iwl_bus *bus, struct fw_desc *desc,
                      const void *data, size_t len);
 void iwl_dealloc_ucode(struct iwl_trans *trans);
 
+int iwl_send_calib_results(struct iwl_trans *trans);
+int iwl_calib_set(struct iwl_trans *trans,
+                 const struct iwl_calib_hdr *cmd, int len);
+void iwl_calib_free_results(struct iwl_trans *trans);
+
 #endif /* __iwl_trans_h__ */
index b365de457b1bd33245ac23214182d231b6db2526..0577212ad3f35cc90ea89ec30be44c1f174b8889 100644 (file)
@@ -217,19 +217,20 @@ static int iwl_set_Xtal_calib(struct iwl_priv *priv)
 {
        struct iwl_calib_xtal_freq_cmd cmd;
        __le16 *xtal_calib =
-               (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_XTAL);
+               (__le16 *)iwl_eeprom_query_addr(priv->shrd, EEPROM_XTAL);
 
        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, (void *)&cmd, sizeof(cmd));
+       return iwl_calib_set(trans(priv), (void *)&cmd, sizeof(cmd));
 }
 
 static int iwl_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_RAW_TEMPERATURE);
+               (__le16 *)iwl_eeprom_query_addr(priv->shrd,
+                                               EEPROM_RAW_TEMPERATURE);
 
        memset(&cmd, 0, sizeof(cmd));
        iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD);
@@ -239,21 +240,22 @@ static int iwl_set_temperature_offset_calib(struct iwl_priv *priv)
 
        IWL_DEBUG_CALIB(priv, "Radio sensor offset: %d\n",
                        le16_to_cpu(cmd.radio_sensor_offset));
-       return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd));
+       return iwl_calib_set(trans(priv), (void *)&cmd, sizeof(cmd));
 }
 
 static int iwl_set_temperature_offset_calib_v2(struct iwl_priv *priv)
 {
        struct iwl_calib_temperature_offset_v2_cmd cmd;
-       __le16 *offset_calib_high = (__le16 *)iwl_eeprom_query_addr(priv,
+       __le16 *offset_calib_high = (__le16 *)iwl_eeprom_query_addr(priv->shrd,
                                     EEPROM_KELVIN_TEMPERATURE);
        __le16 *offset_calib_low =
-               (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_RAW_TEMPERATURE);
+               (__le16 *)iwl_eeprom_query_addr(priv->shrd,
+                                               EEPROM_RAW_TEMPERATURE);
        struct iwl_eeprom_calib_hdr *hdr;
 
        memset(&cmd, 0, sizeof(cmd));
        iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD);
-       hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv,
+       hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv->shrd,
                                                        EEPROM_CALIB_ALL);
        memcpy(&cmd.radio_sensor_offset_high, offset_calib_high,
                sizeof(*offset_calib_high));
@@ -274,7 +276,7 @@ static int iwl_set_temperature_offset_calib_v2(struct iwl_priv *priv)
        IWL_DEBUG_CALIB(priv, "Voltage Ref: %d\n",
                        le16_to_cpu(cmd.burntVoltageRef));
 
-       return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd));
+       return iwl_calib_set(trans(priv), (void *)&cmd, sizeof(cmd));
 }
 
 static int iwl_send_calib_cfg(struct iwl_trans *trans)
@@ -307,7 +309,7 @@ int iwlagn_rx_calib_result(struct iwl_priv *priv,
        /* reduce the size of the length field itself */
        len -= 4;
 
-       if (iwl_calib_set(priv, hdr, len))
+       if (iwl_calib_set(trans(priv), hdr, len))
                IWL_ERR(priv, "Failed to record calibration data %d\n",
                        hdr->op_code);
 
@@ -457,7 +459,7 @@ static int iwl_alive_notify(struct iwl_priv *priv)
                        return ret;
        }
 
-       return iwl_send_calib_results(priv);
+       return iwl_send_calib_results(trans(priv));
 }
 
 
@@ -548,7 +550,7 @@ struct iwlagn_alive_data {
        u8 subtype;
 };
 
-static void iwl_alive_fn(struct iwl_priv *priv,
+static void iwl_alive_fn(struct iwl_trans *trans,
                            struct iwl_rx_packet *pkt,
                            void *data)
 {
@@ -557,14 +559,14 @@ static void iwl_alive_fn(struct iwl_priv *priv,
 
        palive = &pkt->u.alive_frame;
 
-       IWL_DEBUG_FW(priv, "Alive ucode status 0x%08X revision "
+       IWL_DEBUG_FW(trans, "Alive ucode status 0x%08X revision "
                       "0x%01X 0x%01X\n",
                       palive->is_valid, palive->ver_type,
                       palive->ver_subtype);
 
-       priv->device_pointers.error_event_table =
+       trans->shrd->device_pointers.error_event_table =
                le32_to_cpu(palive->error_event_table_ptr);
-       priv->device_pointers.log_event_table =
+       trans->shrd->device_pointers.log_event_table =
                le32_to_cpu(palive->log_event_table_ptr);
 
        alive_data->subtype = palive->ver_subtype;
@@ -575,7 +577,7 @@ static void iwl_alive_fn(struct iwl_priv *priv,
 void iwl_init_notification_wait(struct iwl_shared *shrd,
                                   struct iwl_notification_wait *wait_entry,
                                   u8 cmd,
-                                  void (*fn)(struct iwl_priv *priv,
+                                  void (*fn)(struct iwl_trans *trans,
                                              struct iwl_rx_packet *pkt,
                                              void *data),
                                   void *fn_data)
index 6cf6d6d25e217bd1718fe3cb98f40b5078ad60a6..52bcdf40d5bd64696091179518233d187d3971fb 100644 (file)
@@ -37,7 +37,8 @@ MODULE_AUTHOR("Jouni Malinen");
 MODULE_DESCRIPTION("Software simulator of 802.11 radio(s) for mac80211");
 MODULE_LICENSE("GPL");
 
-int wmediumd_pid;
+static u32 wmediumd_pid;
+
 static int radios = 2;
 module_param(radios, int, 0444);
 MODULE_PARM_DESC(radios, "Number of simulated radios");
@@ -665,7 +666,7 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
        bool ack;
        struct ieee80211_tx_info *txi;
-       int _pid;
+       u32 _pid;
 
        mac80211_hwsim_monitor_rx(hw, skb);
 
@@ -676,7 +677,7 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
        }
 
        /* wmediumd mode check */
-       _pid = wmediumd_pid;
+       _pid = ACCESS_ONCE(wmediumd_pid);
 
        if (_pid)
                return mac80211_hwsim_tx_frame_nl(hw, skb, _pid);
@@ -764,7 +765,7 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
        struct ieee80211_hw *hw = arg;
        struct sk_buff *skb;
        struct ieee80211_tx_info *info;
-       int _pid;
+       u32 _pid;
 
        hwsim_check_magic(vif);
 
@@ -781,7 +782,7 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
        mac80211_hwsim_monitor_rx(hw, skb);
 
        /* wmediumd mode check */
-       _pid = wmediumd_pid;
+       _pid = ACCESS_ONCE(wmediumd_pid);
 
        if (_pid)
                return mac80211_hwsim_tx_frame_nl(hw, skb, _pid);
@@ -1254,7 +1255,7 @@ static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif)
        struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
        struct sk_buff *skb;
        struct ieee80211_pspoll *pspoll;
-       int _pid;
+       u32 _pid;
 
        if (!vp->assoc)
                return;
@@ -1275,7 +1276,7 @@ static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif)
        memcpy(pspoll->ta, mac, ETH_ALEN);
 
        /* wmediumd mode check */
-       _pid = wmediumd_pid;
+       _pid = ACCESS_ONCE(wmediumd_pid);
 
        if (_pid)
                return mac80211_hwsim_tx_frame_nl(data->hw, skb, _pid);
@@ -1292,7 +1293,7 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac,
        struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
        struct sk_buff *skb;
        struct ieee80211_hdr *hdr;
-       int _pid;
+       u32 _pid;
 
        if (!vp->assoc)
                return;
@@ -1314,7 +1315,7 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac,
        memcpy(hdr->addr3, vp->bssid, ETH_ALEN);
 
        /* wmediumd mode check */
-       _pid = wmediumd_pid;
+       _pid = ACCESS_ONCE(wmediumd_pid);
 
        if (_pid)
                return mac80211_hwsim_tx_frame_nl(data->hw, skb, _pid);
@@ -1634,8 +1635,6 @@ static int hwsim_init_netlink(void)
        int rc;
        printk(KERN_INFO "mac80211_hwsim: initializing netlink\n");
 
-       wmediumd_pid = 0;
-
        rc = genl_register_family_with_ops(&hwsim_genl_family,
                hwsim_ops, ARRAY_SIZE(hwsim_ops));
        if (rc)
index 0db97cc84cb4556af9d0d5f44097dd384f20b0ac..787dbe2aa4085dbcee9ad94a608cdd28f93758d3 100644 (file)
@@ -751,17 +751,13 @@ mwifiex_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
 {
        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
 
-       if (priv->disconnect)
-               return -EBUSY;
-
-       priv->disconnect = 1;
        if (mwifiex_deauthenticate(priv, NULL))
                return -EFAULT;
 
        wiphy_dbg(wiphy, "info: successfully disconnected from %pM:"
                " reason code %d\n", priv->cfg_bssid, reason_code);
 
-       queue_work(priv->workqueue, &priv->cfg_workqueue);
+       memset(priv->cfg_bssid, 0, ETH_ALEN);
 
        return 0;
 }
@@ -981,27 +977,32 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
        int ret = 0;
 
-       if (priv->assoc_request)
-               return -EBUSY;
-
        if (priv->bss_mode == NL80211_IFTYPE_ADHOC) {
                wiphy_err(wiphy, "received infra assoc request "
                                "when station is in ibss mode\n");
                goto done;
        }
 
-       priv->assoc_request = -EINPROGRESS;
-
        wiphy_dbg(wiphy, "info: Trying to associate to %s and bssid %pM\n",
               (char *) sme->ssid, sme->bssid);
 
        ret = mwifiex_cfg80211_assoc(priv, sme->ssid_len, sme->ssid, sme->bssid,
                                     priv->bss_mode, sme->channel, sme, 0);
-
-       priv->assoc_request = 1;
 done:
-       priv->assoc_result = ret;
-       queue_work(priv->workqueue, &priv->cfg_workqueue);
+       if (!ret) {
+               cfg80211_connect_result(priv->netdev, priv->cfg_bssid, NULL, 0,
+                                       NULL, 0, WLAN_STATUS_SUCCESS,
+                                       GFP_KERNEL);
+               dev_dbg(priv->adapter->dev,
+                       "info: associated to bssid %pM successfully\n",
+                       priv->cfg_bssid);
+       } else {
+               dev_dbg(priv->adapter->dev,
+                       "info: association to bssid %pM failed\n",
+                       priv->cfg_bssid);
+               memset(priv->cfg_bssid, 0, ETH_ALEN);
+       }
+
        return ret;
 }
 
@@ -1018,28 +1019,29 @@ mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
        struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy);
        int ret = 0;
 
-       if (priv->ibss_join_request)
-               return -EBUSY;
-
        if (priv->bss_mode != NL80211_IFTYPE_ADHOC) {
                wiphy_err(wiphy, "request to join ibss received "
                                "when station is not in ibss mode\n");
                goto done;
        }
 
-       priv->ibss_join_request = -EINPROGRESS;
-
        wiphy_dbg(wiphy, "info: trying to join to %s and bssid %pM\n",
               (char *) params->ssid, params->bssid);
 
        ret = mwifiex_cfg80211_assoc(priv, params->ssid_len, params->ssid,
                                params->bssid, priv->bss_mode,
                                params->channel, NULL, params->privacy);
-
-       priv->ibss_join_request = 1;
 done:
-       priv->ibss_join_result = ret;
-       queue_work(priv->workqueue, &priv->cfg_workqueue);
+       if (!ret) {
+               cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, GFP_KERNEL);
+               dev_dbg(priv->adapter->dev,
+                       "info: joined/created adhoc network with bssid"
+                       " %pM successfully\n", priv->cfg_bssid);
+       } else {
+               dev_dbg(priv->adapter->dev,
+                       "info: failed creating/joining adhoc network\n");
+       }
+
        return ret;
 }
 
@@ -1054,17 +1056,12 @@ mwifiex_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
 {
        struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy);
 
-       if (priv->disconnect)
-               return -EBUSY;
-
-       priv->disconnect = 1;
-
        wiphy_dbg(wiphy, "info: disconnecting from essid %pM\n",
                        priv->cfg_bssid);
        if (mwifiex_deauthenticate(priv, NULL))
                return -EFAULT;
 
-       queue_work(priv->workqueue, &priv->cfg_workqueue);
+       memset(priv->cfg_bssid, 0, ETH_ALEN);
 
        return 0;
 }
@@ -1081,15 +1078,42 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev,
                      struct cfg80211_scan_request *request)
 {
        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+       int i;
+       struct ieee80211_channel *chan;
 
        wiphy_dbg(wiphy, "info: received scan request on %s\n", dev->name);
 
-       if (priv->scan_request && priv->scan_request != request)
-               return -EBUSY;
-
        priv->scan_request = request;
 
-       queue_work(priv->workqueue, &priv->cfg_workqueue);
+       priv->user_scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg),
+                                       GFP_KERNEL);
+       if (!priv->user_scan_cfg) {
+               dev_err(priv->adapter->dev, "failed to alloc scan_req\n");
+               return -ENOMEM;
+       }
+       for (i = 0; i < request->n_ssids; i++) {
+               memcpy(priv->user_scan_cfg->ssid_list[i].ssid,
+                       request->ssids[i].ssid, request->ssids[i].ssid_len);
+               priv->user_scan_cfg->ssid_list[i].max_len =
+                       request->ssids[i].ssid_len;
+       }
+       for (i = 0; i < request->n_channels; i++) {
+               chan = request->channels[i];
+               priv->user_scan_cfg->chan_list[i].chan_number = chan->hw_value;
+               priv->user_scan_cfg->chan_list[i].radio_type = chan->band;
+
+               if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)
+                       priv->user_scan_cfg->chan_list[i].scan_type =
+                               MWIFIEX_SCAN_TYPE_PASSIVE;
+               else
+                       priv->user_scan_cfg->chan_list[i].scan_type =
+                               MWIFIEX_SCAN_TYPE_ACTIVE;
+
+               priv->user_scan_cfg->chan_list[i].scan_time = 0;
+       }
+       if (mwifiex_set_user_scan_ioctl(priv, priv->user_scan_cfg))
+               return -EFAULT;
+
        return 0;
 }
 
@@ -1295,10 +1319,6 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev)
 
        priv->media_connected = false;
 
-       cancel_work_sync(&priv->cfg_workqueue);
-       flush_workqueue(priv->workqueue);
-       destroy_workqueue(priv->workqueue);
-
        priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
 
        return 0;
@@ -1376,9 +1396,6 @@ int mwifiex_register_cfg80211(struct mwifiex_private *priv)
        memcpy(wdev->wiphy->perm_addr, priv->curr_addr, ETH_ALEN);
        wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
 
-       /* We are using custom domains */
-       wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
-
        /* Reserve space for bss band information */
        wdev->wiphy->bss_priv_size = sizeof(u8);
 
@@ -1407,100 +1424,3 @@ int mwifiex_register_cfg80211(struct mwifiex_private *priv)
 
        return ret;
 }
-
-/*
- * This function handles the result of different pending network operations.
- *
- * The following operations are handled and CFG802.11 subsystem is
- * notified accordingly -
- *      - Scan request completion
- *      - Association request completion
- *      - IBSS join request completion
- *      - Disconnect request completion
- */
-void
-mwifiex_cfg80211_results(struct work_struct *work)
-{
-       struct mwifiex_private *priv =
-               container_of(work, struct mwifiex_private, cfg_workqueue);
-       struct mwifiex_user_scan_cfg *scan_req;
-       int ret = 0, i;
-       struct ieee80211_channel *chan;
-
-       if (priv->scan_request) {
-               scan_req = kzalloc(sizeof(struct mwifiex_user_scan_cfg),
-                                  GFP_KERNEL);
-               if (!scan_req) {
-                       dev_err(priv->adapter->dev, "failed to alloc "
-                                                   "scan_req\n");
-                       return;
-               }
-               for (i = 0; i < priv->scan_request->n_ssids; i++) {
-                       memcpy(scan_req->ssid_list[i].ssid,
-                                       priv->scan_request->ssids[i].ssid,
-                                       priv->scan_request->ssids[i].ssid_len);
-                       scan_req->ssid_list[i].max_len =
-                                       priv->scan_request->ssids[i].ssid_len;
-               }
-               for (i = 0; i < priv->scan_request->n_channels; i++) {
-                       chan = priv->scan_request->channels[i];
-                       scan_req->chan_list[i].chan_number = chan->hw_value;
-                       scan_req->chan_list[i].radio_type = chan->band;
-                       if (chan->flags & IEEE80211_CHAN_DISABLED)
-                               scan_req->chan_list[i].scan_type =
-                                       MWIFIEX_SCAN_TYPE_PASSIVE;
-                       else
-                               scan_req->chan_list[i].scan_type =
-                                       MWIFIEX_SCAN_TYPE_ACTIVE;
-                       scan_req->chan_list[i].scan_time = 0;
-               }
-               if (mwifiex_set_user_scan_ioctl(priv, scan_req))
-                       ret = -EFAULT;
-               priv->scan_result_status = ret;
-               dev_dbg(priv->adapter->dev, "info: %s: sending scan results\n",
-                                                       __func__);
-               cfg80211_scan_done(priv->scan_request,
-                               (priv->scan_result_status < 0));
-               priv->scan_request = NULL;
-               kfree(scan_req);
-       }
-
-       if (priv->assoc_request == 1) {
-               if (!priv->assoc_result) {
-                       cfg80211_connect_result(priv->netdev, priv->cfg_bssid,
-                                               NULL, 0, NULL, 0,
-                                               WLAN_STATUS_SUCCESS,
-                                               GFP_KERNEL);
-                       dev_dbg(priv->adapter->dev,
-                               "info: associated to bssid %pM successfully\n",
-                              priv->cfg_bssid);
-               } else {
-                       dev_dbg(priv->adapter->dev,
-                               "info: association to bssid %pM failed\n",
-                              priv->cfg_bssid);
-                       memset(priv->cfg_bssid, 0, ETH_ALEN);
-               }
-               priv->assoc_request = 0;
-               priv->assoc_result = 0;
-       }
-
-       if (priv->ibss_join_request == 1) {
-               if (!priv->ibss_join_result) {
-                       cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid,
-                                            GFP_KERNEL);
-                       dev_dbg(priv->adapter->dev,
-                               "info: joined/created adhoc network with bssid"
-                                       " %pM successfully\n", priv->cfg_bssid);
-               } else {
-                       dev_dbg(priv->adapter->dev,
-                               "info: failed creating/joining adhoc network\n");
-               }
-               priv->ibss_join_request = 0;
-               priv->ibss_join_result = 0;
-       }
-
-       if (priv->disconnect) {
-               memset(priv->cfg_bssid, 0, ETH_ALEN);
-               priv->disconnect = 0;
-       }
-}
index 8d010f2500c5031c6f7cf64853e988ec8010a872..76c76c60438b4f52fb86632fccb50234bc2ce37a 100644 (file)
@@ -26,5 +26,4 @@
 
 int mwifiex_register_cfg80211(struct mwifiex_private *);
 
-void mwifiex_cfg80211_results(struct work_struct *work);
 #endif
index ac278156d390ea901d37eda9819abdf2de26edcf..6e0a3eaecf7070bcdcce90eb91e63d7fe6cc6aab 100644 (file)
@@ -939,7 +939,6 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)
 {
        struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL;
        unsigned long cmd_flags;
-       unsigned long cmd_pending_q_flags;
        unsigned long scan_pending_q_flags;
        uint16_t cancel_scan_cmd = false;
 
@@ -949,12 +948,9 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)
                cmd_node = adapter->curr_cmd;
                cmd_node->wait_q_enabled = false;
                cmd_node->cmd_flag |= CMD_F_CANCELED;
-               spin_lock_irqsave(&adapter->cmd_pending_q_lock,
-                                 cmd_pending_q_flags);
-               list_del(&cmd_node->list);
-               spin_unlock_irqrestore(&adapter->cmd_pending_q_lock,
-                                      cmd_pending_q_flags);
                mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
+               mwifiex_complete_cmd(adapter, adapter->curr_cmd);
+               adapter->curr_cmd = NULL;
                spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
        }
 
@@ -981,7 +977,6 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)
                spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
        }
        adapter->cmd_wait_q.status = -1;
-       mwifiex_complete_cmd(adapter, adapter->curr_cmd);
 }
 
 /*
index 26940455255ba4637fdd31ec19a3407640f71e87..244c728ef9dcc63f968617e7e557874d8f4f4977 100644 (file)
@@ -282,6 +282,45 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
        adapter->arp_filter_size = 0;
 }
 
+/*
+ * This function sets trans_start per tx_queue
+ */
+void mwifiex_set_trans_start(struct net_device *dev)
+{
+       int i;
+
+       for (i = 0; i < dev->num_tx_queues; i++)
+               netdev_get_tx_queue(dev, i)->trans_start = jiffies;
+
+       dev->trans_start = jiffies;
+}
+
+/*
+ * This function wakes up all queues in net_device
+ */
+void mwifiex_wake_up_net_dev_queue(struct net_device *netdev,
+                                       struct mwifiex_adapter *adapter)
+{
+       unsigned long dev_queue_flags;
+
+       spin_lock_irqsave(&adapter->queue_lock, dev_queue_flags);
+       netif_tx_wake_all_queues(netdev);
+       spin_unlock_irqrestore(&adapter->queue_lock, dev_queue_flags);
+}
+
+/*
+ * This function stops all queues in net_device
+ */
+void mwifiex_stop_net_dev_queue(struct net_device *netdev,
+                                       struct mwifiex_adapter *adapter)
+{
+       unsigned long dev_queue_flags;
+
+       spin_lock_irqsave(&adapter->queue_lock, dev_queue_flags);
+       netif_tx_stop_all_queues(netdev);
+       spin_unlock_irqrestore(&adapter->queue_lock, dev_queue_flags);
+}
+
 /*
  *  This function releases the lock variables and frees the locks and
  *  associated locks.
@@ -359,6 +398,7 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter)
        spin_lock_init(&adapter->int_lock);
        spin_lock_init(&adapter->main_proc_lock);
        spin_lock_init(&adapter->mwifiex_cmd_lock);
+       spin_lock_init(&adapter->queue_lock);
        for (i = 0; i < adapter->priv_num; i++) {
                if (adapter->priv[i]) {
                        priv = adapter->priv[i];
index 67e6db7d672ddf5fbeb614395bdda7c76b2dab56..84be196188ccc75bfbaf97f1e7bd8c4ab2fd654b 100644 (file)
@@ -401,7 +401,7 @@ mwifiex_fill_buffer(struct sk_buff *skb)
 static int
 mwifiex_open(struct net_device *dev)
 {
-       netif_start_queue(dev);
+       netif_tx_start_all_queues(dev);
        return 0;
 }
 
@@ -465,8 +465,8 @@ mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
        atomic_inc(&priv->adapter->tx_pending);
 
        if (atomic_read(&priv->adapter->tx_pending) >= MAX_TX_PENDING) {
-               netif_stop_queue(priv->netdev);
-               dev->trans_start = jiffies;
+               mwifiex_set_trans_start(dev);
+               mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter);
        }
 
        queue_work(priv->adapter->workqueue, &priv->adapter->main_work);
@@ -533,7 +533,7 @@ mwifiex_tx_timeout(struct net_device *dev)
 
        dev_err(priv->adapter->dev, "%lu : Tx timeout, bss_index=%d\n",
                                jiffies, priv->bss_index);
-       dev->trans_start = jiffies;
+       mwifiex_set_trans_start(dev);
        priv->num_tx_timeout++;
 }
 
@@ -586,8 +586,6 @@ void mwifiex_init_priv_params(struct mwifiex_private *priv,
        priv->media_connected = false;
        memset(&priv->nick_name, 0, sizeof(priv->nick_name));
        priv->num_tx_timeout = 0;
-       priv->workqueue = create_singlethread_workqueue("cfg80211_wq");
-       INIT_WORK(&priv->cfg_workqueue, mwifiex_cfg80211_results);
        memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN);
 }
 
@@ -793,7 +791,8 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
                priv = adapter->priv[i];
                if (priv && priv->netdev) {
                        if (!netif_queue_stopped(priv->netdev))
-                               netif_stop_queue(priv->netdev);
+                               mwifiex_stop_net_dev_queue(priv->netdev,
+                                                               adapter);
                        if (netif_carrier_ok(priv->netdev))
                                netif_carrier_off(priv->netdev);
                }
index 3861a617c0e13e3b5b61a768924e20bfb2784715..9207fc64641e265d99a6b30ef9ab4c3dcc9047eb 100644 (file)
@@ -453,15 +453,8 @@ struct mwifiex_private {
        u8 scan_pending_on_block;
        u8 report_scan_result;
        struct cfg80211_scan_request *scan_request;
-       int scan_result_status;
-       int assoc_request;
-       u16 assoc_result;
-       int ibss_join_request;
-       u16 ibss_join_result;
-       bool disconnect;
+       struct mwifiex_user_scan_cfg *user_scan_cfg;
        u8 cfg_bssid[6];
-       struct workqueue_struct *workqueue;
-       struct work_struct cfg_workqueue;
        u8 country_code[IEEE80211_COUNTRY_STRING_LEN];
        struct wps wps;
        u8 scan_block;
@@ -655,10 +648,19 @@ struct mwifiex_adapter {
        struct mwifiex_wait_queue cmd_wait_q;
        u8 scan_wait_q_woken;
        struct cmd_ctrl_node *cmd_queued;
+       spinlock_t queue_lock;          /* lock for tx queues */
 };
 
 int mwifiex_init_lock_list(struct mwifiex_adapter *adapter);
 
+void mwifiex_set_trans_start(struct net_device *dev);
+
+void mwifiex_stop_net_dev_queue(struct net_device *netdev,
+               struct mwifiex_adapter *adapter);
+
+void mwifiex_wake_up_net_dev_queue(struct net_device *netdev,
+               struct mwifiex_adapter *adapter);
+
 int mwifiex_init_fw(struct mwifiex_adapter *adapter);
 
 int mwifiex_init_fw_complete(struct mwifiex_adapter *adapter);
index a2f32008f9a80810355c8c4cc145ada8199d9516..405350940a45aad728059f0909cdcdd6098de0b3 100644 (file)
@@ -386,7 +386,7 @@ static int mwifiex_pcie_create_txbd_ring(struct mwifiex_adapter *adapter)
        card->txbd_ring_vbase = kzalloc(card->txbd_ring_size, GFP_KERNEL);
        if (!card->txbd_ring_vbase) {
                dev_err(adapter->dev, "Unable to allocate buffer for txbd ring.\n");
-               return -1;
+               return -ENOMEM;
        }
        card->txbd_ring_pbase = virt_to_phys(card->txbd_ring_vbase);
 
@@ -476,7 +476,7 @@ static int mwifiex_pcie_create_rxbd_ring(struct mwifiex_adapter *adapter)
        if (!card->rxbd_ring_vbase) {
                dev_err(adapter->dev, "Unable to allocate buffer for "
                                "rxbd_ring.\n");
-               return -1;
+               return -ENOMEM;
        }
        card->rxbd_ring_pbase = virt_to_phys(card->rxbd_ring_vbase);
 
@@ -569,7 +569,7 @@ static int mwifiex_pcie_create_evtbd_ring(struct mwifiex_adapter *adapter)
        if (!card->evtbd_ring_vbase) {
                dev_err(adapter->dev, "Unable to allocate buffer. "
                                "Terminating download\n");
-               return -1;
+               return -ENOMEM;
        }
        card->evtbd_ring_pbase = virt_to_phys(card->evtbd_ring_vbase);
 
@@ -1231,15 +1231,13 @@ static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter,
        if (rdptr >= MWIFIEX_MAX_EVT_BD) {
                dev_err(adapter->dev, "event_complete: Invalid rdptr 0x%x\n",
                                        rdptr);
-               ret = -EINVAL;
-               goto done;
+               return -EINVAL;
        }
 
        /* Read the event ring write pointer set by firmware */
        if (mwifiex_read_reg(adapter, REG_EVTBD_WRPTR, &wrptr)) {
                dev_err(adapter->dev, "event_complete: failed to read REG_EVTBD_WRPTR\n");
-               ret = -1;
-               goto done;
+               return -1;
        }
 
        if (!card->evt_buf_list[rdptr]) {
@@ -1268,15 +1266,9 @@ static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter,
        /* Write the event ring read pointer in to REG_EVTBD_RDPTR */
        if (mwifiex_write_reg(adapter, REG_EVTBD_RDPTR, card->evtbd_rdptr)) {
                dev_err(adapter->dev, "event_complete: failed to read REG_EVTBD_RDPTR\n");
-               ret = -1;
-               goto done;
+               return -1;
        }
 
-done:
-       /* Free the buffer for failure case */
-       if (ret && skb)
-               dev_kfree_skb_any(skb);
-
        dev_dbg(adapter->dev, "info: Check Events Again\n");
        ret = mwifiex_pcie_process_event_ready(adapter);
 
index b8b9d37b01a948673278f5beccb9ce87c916d922..e2e715666bcabf36815f088a914a8ee20fd7c9b8 100644 (file)
@@ -1391,11 +1391,8 @@ int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv,
 {
        int status;
 
-       priv->adapter->scan_wait_q_woken = false;
-
        status = mwifiex_scan_networks(priv, scan_req);
-       if (!status)
-               status = mwifiex_wait_queue_complete(priv->adapter);
+       queue_work(priv->adapter->workqueue, &priv->adapter->main_work);
 
        return status;
 }
@@ -1796,6 +1793,14 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
                        up(&priv->async_sem);
                }
 
+               if (priv->user_scan_cfg) {
+                       dev_dbg(priv->adapter->dev, "info: %s: sending scan "
+                                                       "results\n", __func__);
+                       cfg80211_scan_done(priv->scan_request, 0);
+                       priv->scan_request = NULL;
+                       kfree(priv->user_scan_cfg);
+                       priv->user_scan_cfg = NULL;
+               }
        } else {
                /* Get scan command from scan_pending_q and put to
                   cmd_pending_q */
index 702452b505c33c3e29f00dc45b576879524a3eed..d39d8457f25284b8b81f871eddcb36937d4a268d 100644 (file)
@@ -1087,7 +1087,7 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter,
                                           (adapter->ioport | 0x1000 |
                                            (card->mpa_rx.ports << 4)) +
                                           card->mpa_rx.start_port, 1))
-                       return -1;
+                       goto error;
 
                curr_ptr = card->mpa_rx.buf;
 
@@ -1130,12 +1130,29 @@ rx_curr_single:
                if (mwifiex_sdio_card_to_host(adapter, &pkt_type,
                                              skb->data, skb->len,
                                              adapter->ioport + port))
-                       return -1;
+                       goto error;
 
                mwifiex_decode_rx_packet(adapter, skb, pkt_type);
        }
 
        return 0;
+
+error:
+       if (MP_RX_AGGR_IN_PROGRESS(card)) {
+               /* Multiport-aggregation transfer failed - cleanup */
+               for (pind = 0; pind < card->mpa_rx.pkt_cnt; pind++) {
+                       /* copy pkt to deaggr buf */
+                       skb_deaggr = card->mpa_rx.skb_arr[pind];
+                       dev_kfree_skb_any(skb_deaggr);
+               }
+               MP_RX_AGGR_BUF_RESET(card);
+       }
+
+       if (f_do_rx_cur)
+               /* Single transfer pending. Free curr buff also */
+               dev_kfree_skb_any(skb);
+
+       return -1;
 }
 
 /*
@@ -1271,7 +1288,6 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
 
                                dev_dbg(adapter->dev,
                                                "info: CFG reg val =%x\n", cr);
-                               dev_kfree_skb_any(skb);
                                return -1;
                        }
                }
index f204810e83389bfa4085c6dd5dbc39daa26ee70f..d7aa21da84d0124fd78a181da4bd7d711094c6eb 100644 (file)
@@ -115,18 +115,17 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv)
        if (adapter->num_cmd_timeout && adapter->curr_cmd)
                return;
        priv->media_connected = false;
-       if (!priv->disconnect) {
-               priv->disconnect = 1;
-               dev_dbg(adapter->dev, "info: successfully disconnected from"
-                               " %pM: reason code %d\n", priv->cfg_bssid,
-                               WLAN_REASON_DEAUTH_LEAVING);
-               cfg80211_disconnected(priv->netdev,
-                               WLAN_REASON_DEAUTH_LEAVING, NULL, 0,
-                               GFP_KERNEL);
-               queue_work(priv->workqueue, &priv->cfg_workqueue);
+       dev_dbg(adapter->dev, "info: successfully disconnected from"
+                       " %pM: reason code %d\n", priv->cfg_bssid,
+                       WLAN_REASON_DEAUTH_LEAVING);
+       if (priv->bss_mode == NL80211_IFTYPE_STATION) {
+               cfg80211_disconnected(priv->netdev, WLAN_REASON_DEAUTH_LEAVING,
+                                     NULL, 0, GFP_KERNEL);
        }
+       memset(priv->cfg_bssid, 0, ETH_ALEN);
+
        if (!netif_queue_stopped(priv->netdev))
-               netif_stop_queue(priv->netdev);
+               mwifiex_stop_net_dev_queue(priv->netdev, adapter);
        if (netif_carrier_ok(priv->netdev))
                netif_carrier_off(priv->netdev);
        /* Reset wireless stats signal info */
@@ -201,7 +200,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
                if (!netif_carrier_ok(priv->netdev))
                        netif_carrier_on(priv->netdev);
                if (netif_queue_stopped(priv->netdev))
-                       netif_wake_queue(priv->netdev);
+                       mwifiex_wake_up_net_dev_queue(priv->netdev, adapter);
                break;
 
        case EVENT_DEAUTHENTICATED:
@@ -292,7 +291,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
                priv->adhoc_is_link_sensed = false;
                mwifiex_clean_txrx(priv);
                if (!netif_queue_stopped(priv->netdev))
-                       netif_stop_queue(priv->netdev);
+                       mwifiex_stop_net_dev_queue(priv->netdev, adapter);
                if (netif_carrier_ok(priv->netdev))
                        netif_carrier_off(priv->netdev);
                break;
index 4b6f5539657d6cd250c07939cda005c02e66fba0..6d990c798a20f83b7be40334b3305b9cd7f57efa 100644 (file)
@@ -234,7 +234,7 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
                                      "associating...\n");
 
                if (!netif_queue_stopped(priv->netdev))
-                       netif_stop_queue(priv->netdev);
+                       mwifiex_stop_net_dev_queue(priv->netdev, adapter);
 
                /* Clear any past association response stored for
                 * application retrieval */
@@ -265,7 +265,7 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
                ret = mwifiex_check_network_compatibility(priv, bss_desc);
 
                if (!netif_queue_stopped(priv->netdev))
-                       netif_stop_queue(priv->netdev);
+                       mwifiex_stop_net_dev_queue(priv->netdev, adapter);
 
                if (!ret) {
                        dev_dbg(adapter->dev, "info: network found in scan"
index a206f412875f74647d8b7362fc17bb7c674bc047..d9274a1b77acabce253e6400af854d71c29b814b 100644 (file)
@@ -134,7 +134,7 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter,
        if (!priv)
                goto done;
 
-       priv->netdev->trans_start = jiffies;
+       mwifiex_set_trans_start(priv->netdev);
        if (!status) {
                priv->stats.tx_packets++;
                priv->stats.tx_bytes += skb->len;
@@ -152,7 +152,8 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter,
                if ((GET_BSS_ROLE(tpriv) == MWIFIEX_BSS_ROLE_STA)
                                && (tpriv->media_connected)) {
                        if (netif_queue_stopped(tpriv->netdev))
-                               netif_wake_queue(tpriv->netdev);
+                               mwifiex_wake_up_net_dev_queue(tpriv->netdev,
+                                                               adapter);
                }
        }
 done:
index bf0acff07807866f5aa28049a63922ae40ee2ebc..ede3c58e67836e1800662b2c5399e82e85b59442 100644 (file)
@@ -160,7 +160,7 @@ void rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
  exit_fail:
        rt2x00queue_pause_queue(queue);
  exit_free_skb:
-       dev_kfree_skb_any(skb);
+       ieee80211_free_txskb(hw, skb);
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_tx);
 
index a13ecfce482554f4fb62bbf3bd2caeaabd639a21..d81a6021a30f5f8b9f9b85afb750b3d8f235c846 100644 (file)
@@ -448,12 +448,11 @@ int rtl_init_core(struct ieee80211_hw *hw)
 
        /* <4> locks */
        mutex_init(&rtlpriv->locks.conf_mutex);
-       spin_lock_init(&rtlpriv->locks.ips_lock);
+       mutex_init(&rtlpriv->locks.ps_mutex);
        spin_lock_init(&rtlpriv->locks.irq_th_lock);
        spin_lock_init(&rtlpriv->locks.h2c_lock);
        spin_lock_init(&rtlpriv->locks.rf_ps_lock);
        spin_lock_init(&rtlpriv->locks.rf_lock);
-       spin_lock_init(&rtlpriv->locks.lps_lock);
        spin_lock_init(&rtlpriv->locks.waitq_lock);
        spin_lock_init(&rtlpriv->locks.cck_and_rw_pagea_lock);
 
index 91f0525364eac279619a547fca446194d53dc334..0d4d242849b46dc72f5a2d59bcd412135c73f3ee 100644 (file)
@@ -610,7 +610,7 @@ tx_status_ok:
        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);
+               schedule_work(&rtlpriv->works.lps_leave_work);
        }
 }
 
@@ -736,7 +736,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
                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);
+                       schedule_work(&rtlpriv->works.lps_leave_work);
                }
 
                dev_kfree_skb_any(skb);
@@ -903,11 +903,6 @@ static void _rtl_pci_irq_tasklet(struct ieee80211_hw *hw)
        _rtl_pci_tx_chk_waitq(hw);
 }
 
-static void _rtl_pci_ips_leave_tasklet(struct ieee80211_hw *hw)
-{
-       rtl_lps_leave(hw);
-}
-
 static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -945,6 +940,15 @@ static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw)
        return;
 }
 
+static void rtl_lps_leave_work_callback(struct work_struct *work)
+{
+       struct rtl_works *rtlworks =
+           container_of(work, struct rtl_works, lps_leave_work);
+       struct ieee80211_hw *hw = rtlworks->hw;
+
+       rtl_lps_leave(hw);
+}
+
 static void _rtl_pci_init_trx_var(struct ieee80211_hw *hw)
 {
        struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
@@ -1006,9 +1010,7 @@ static void _rtl_pci_init_struct(struct ieee80211_hw *hw,
        tasklet_init(&rtlpriv->works.irq_prepare_bcn_tasklet,
                     (void (*)(unsigned long))_rtl_pci_prepare_bcn_tasklet,
                     (unsigned long)hw);
-       tasklet_init(&rtlpriv->works.ips_leave_tasklet,
-                    (void (*)(unsigned long))_rtl_pci_ips_leave_tasklet,
-                    (unsigned long)hw);
+       INIT_WORK(&rtlpriv->works.lps_leave_work, rtl_lps_leave_work_callback);
 }
 
 static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw,
@@ -1478,7 +1480,7 @@ static void rtl_pci_deinit(struct ieee80211_hw *hw)
 
        synchronize_irq(rtlpci->pdev->irq);
        tasklet_kill(&rtlpriv->works.irq_tasklet);
-       tasklet_kill(&rtlpriv->works.ips_leave_tasklet);
+       cancel_work_sync(&rtlpriv->works.lps_leave_work);
 
        flush_workqueue(rtlpriv->works.rtl_wq);
        destroy_workqueue(rtlpriv->works.rtl_wq);
@@ -1553,7 +1555,7 @@ static void rtl_pci_stop(struct ieee80211_hw *hw)
        set_hal_stop(rtlhal);
 
        rtlpriv->cfg->ops->disable_interrupt(hw);
-       tasklet_kill(&rtlpriv->works.ips_leave_tasklet);
+       cancel_work_sync(&rtlpriv->works.lps_leave_work);
 
        spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags);
        while (ppsc->rfchange_inprogress) {
index 55c8e50f45fd143b7e606894c71e072c97480f2a..a14a68b246354a9674320be31a142f335ba14ea4 100644 (file)
@@ -241,7 +241,7 @@ void rtl_ips_nic_on(struct ieee80211_hw *hw)
        if (mac->opmode != NL80211_IFTYPE_STATION)
                return;
 
-       spin_lock(&rtlpriv->locks.ips_lock);
+       mutex_lock(&rtlpriv->locks.ps_mutex);
 
        if (ppsc->inactiveps) {
                rtstate = ppsc->rfpwr_state;
@@ -257,7 +257,7 @@ void rtl_ips_nic_on(struct ieee80211_hw *hw)
                }
        }
 
-       spin_unlock(&rtlpriv->locks.ips_lock);
+       mutex_unlock(&rtlpriv->locks.ps_mutex);
 }
 
 /*for FW LPS*/
@@ -395,7 +395,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw)
        if (mac->link_state != MAC80211_LINKED)
                return;
 
-       spin_lock_irq(&rtlpriv->locks.lps_lock);
+       mutex_lock(&rtlpriv->locks.ps_mutex);
 
        /* Idle for a while if we connect to AP a while ago. */
        if (mac->cnt_after_linked >= 2) {
@@ -407,7 +407,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw)
                }
        }
 
-       spin_unlock_irq(&rtlpriv->locks.lps_lock);
+       mutex_unlock(&rtlpriv->locks.ps_mutex);
 }
 
 /*Leave the leisure power save mode.*/
@@ -416,9 +416,8 @@ void rtl_lps_leave(struct ieee80211_hw *hw)
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-       unsigned long flags;
 
-       spin_lock_irqsave(&rtlpriv->locks.lps_lock, flags);
+       mutex_lock(&rtlpriv->locks.ps_mutex);
 
        if (ppsc->fwctrl_lps) {
                if (ppsc->dot11_psmode != EACTIVE) {
@@ -439,7 +438,7 @@ void rtl_lps_leave(struct ieee80211_hw *hw)
                        rtl_lps_set_psmode(hw, EACTIVE);
                }
        }
-       spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flags);
+       mutex_unlock(&rtlpriv->locks.ps_mutex);
 }
 
 /* For sw LPS*/
@@ -540,9 +539,9 @@ void rtl_swlps_rf_awake(struct ieee80211_hw *hw)
                RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM);
        }
 
-       spin_lock_irq(&rtlpriv->locks.lps_lock);
+       mutex_lock(&rtlpriv->locks.ps_mutex);
        rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS);
-       spin_unlock_irq(&rtlpriv->locks.lps_lock);
+       mutex_unlock(&rtlpriv->locks.ps_mutex);
 }
 
 void rtl_swlps_rfon_wq_callback(void *data)
@@ -575,9 +574,9 @@ void rtl_swlps_rf_sleep(struct ieee80211_hw *hw)
        if (rtlpriv->link_info.busytraffic)
                return;
 
-       spin_lock_irq(&rtlpriv->locks.lps_lock);
+       mutex_lock(&rtlpriv->locks.ps_mutex);
        rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS);
-       spin_unlock_irq(&rtlpriv->locks.lps_lock);
+       mutex_unlock(&rtlpriv->locks.ps_mutex);
 
        if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM &&
                !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) {
index f3c132b55d42b5ada63c3a25761c8958fc935952..085dccdbd1b63779d071f12b8aa9f89b0f08f752 100644 (file)
@@ -1544,14 +1544,13 @@ struct rtl_hal_cfg {
 struct rtl_locks {
        /* mutex */
        struct mutex conf_mutex;
+       struct mutex ps_mutex;
 
        /*spin lock */
-       spinlock_t ips_lock;
        spinlock_t irq_th_lock;
        spinlock_t h2c_lock;
        spinlock_t rf_ps_lock;
        spinlock_t rf_lock;
-       spinlock_t lps_lock;
        spinlock_t waitq_lock;
 
        /*Dual mac*/
@@ -1576,7 +1575,8 @@ struct rtl_works {
        /* For SW LPS */
        struct delayed_work ps_work;
        struct delayed_work ps_rfon_wq;
-       struct tasklet_struct ips_leave_tasklet;
+
+       struct work_struct lps_leave_work;
 };
 
 struct rtl_debug {
index bde1d862bdd595cc88f6943d40d44f949c51b8f9..7537c401a4487174a0d50680b1d84e68c3e16675 100644 (file)
@@ -186,32 +186,6 @@ out:
        return ret;
 }
 
-int wl1271_acx_pd_threshold(struct wl1271 *wl)
-{
-       struct acx_packet_detection *pd;
-       int ret;
-
-       wl1271_debug(DEBUG_ACX, "acx data pd threshold");
-
-       pd = kzalloc(sizeof(*pd), GFP_KERNEL);
-       if (!pd) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       pd->threshold = cpu_to_le32(wl->conf.rx.packet_detection_threshold);
-
-       ret = wl1271_cmd_configure(wl, ACX_PD_THRESHOLD, pd, sizeof(*pd));
-       if (ret < 0) {
-               wl1271_warning("failed to set pd threshold: %d", ret);
-               goto out;
-       }
-
-out:
-       kfree(pd);
-       return ret;
-}
-
 int wl1271_acx_slot(struct wl1271 *wl, struct wl12xx_vif *wlvif,
                    enum acx_slot_type slot_time)
 {
index b2d85bea6378a6feaed850faec2c6e506c2a504c..69892b40c2dfc850cd44b434a155c5ce81da4c6c 100644 (file)
@@ -171,13 +171,6 @@ struct acx_rx_msdu_lifetime {
        __le32 lifetime;
 } __packed;
 
-struct acx_packet_detection {
-       struct acx_header header;
-
-       __le32 threshold;
-} __packed;
-
-
 enum acx_slot_type {
        SLOT_TIME_LONG = 0,
        SLOT_TIME_SHORT = 1,
@@ -1238,7 +1231,6 @@ int wl1271_acx_feature_cfg(struct wl1271 *wl, struct wl12xx_vif *wlvif);
 int wl1271_acx_mem_map(struct wl1271 *wl,
                       struct acx_header *mem_map, size_t len);
 int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl);
-int wl1271_acx_pd_threshold(struct wl1271 *wl);
 int wl1271_acx_slot(struct wl1271 *wl, struct wl12xx_vif *wlvif,
                    enum acx_slot_type slot_time);
 int wl1271_acx_group_address_tbl(struct wl1271 *wl, struct wl12xx_vif *wlvif,
index 2e14b436101f9f2e2d1dde9bf4e8ef5328f11f58..15eb3a9c30ca11907ea92ef4aaf3ce794c91ea0c 100644 (file)
@@ -317,12 +317,19 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
 {
        struct wl1271 *wl = file->private_data;
        int res = 0;
-       char buf[1024];
+       ssize_t ret;
+       char *buf;
+
+#define DRIVER_STATE_BUF_LEN 1024
+
+       buf = kmalloc(DRIVER_STATE_BUF_LEN, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
 
        mutex_lock(&wl->mutex);
 
 #define DRIVER_STATE_PRINT(x, fmt)   \
-       (res += scnprintf(buf + res, sizeof(buf) - res,\
+       (res += scnprintf(buf + res, DRIVER_STATE_BUF_LEN - res,\
                          #x " = " fmt "\n", wl->x))
 
 #define DRIVER_STATE_PRINT_LONG(x) DRIVER_STATE_PRINT(x, "%ld")
@@ -373,10 +380,13 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
 #undef DRIVER_STATE_PRINT_LHEX
 #undef DRIVER_STATE_PRINT_STR
 #undef DRIVER_STATE_PRINT
+#undef DRIVER_STATE_BUF_LEN
 
        mutex_unlock(&wl->mutex);
 
-       return simple_read_from_buffer(user_buf, count, ppos, buf, res);
+       ret = simple_read_from_buffer(user_buf, count, ppos, buf, res);
+       kfree(buf);
+       return ret;
 }
 
 static const struct file_operations driver_state_ops = {
index 88891cdfdd4adc7f1bb67e27771e8a959517456a..ca7ee59e4505b297c104197bfde176e34336458b 100644 (file)
@@ -223,17 +223,6 @@ static int wl12xx_init_rx_config(struct wl1271 *wl)
        return 0;
 }
 
-int wl1271_init_phy_config(struct wl1271 *wl)
-{
-       int ret;
-
-       ret = wl1271_acx_pd_threshold(wl);
-       if (ret < 0)
-               return ret;
-
-       return 0;
-}
-
 static int wl12xx_init_phy_vif_config(struct wl1271 *wl,
                                            struct wl12xx_vif *wlvif)
 {
@@ -328,12 +317,6 @@ static int wl1271_sta_hw_init(struct wl1271 *wl, struct wl12xx_vif *wlvif)
 {
        int ret;
 
-       if (wl->chip.id != CHIP_ID_1283_PG20) {
-               ret = wl1271_cmd_ext_radio_parms(wl);
-               if (ret < 0)
-                       return ret;
-       }
-
        /* PS config */
        ret = wl12xx_acx_config_ps(wl, wlvif);
        if (ret < 0)
@@ -659,19 +642,24 @@ int wl1271_hw_init(struct wl1271 *wl)
 {
        int ret;
 
-       if (wl->chip.id == CHIP_ID_1283_PG20)
+       if (wl->chip.id == CHIP_ID_1283_PG20) {
                ret = wl128x_cmd_general_parms(wl);
-       else
-               ret = wl1271_cmd_general_parms(wl);
-       if (ret < 0)
-               return ret;
-
-       if (wl->chip.id == CHIP_ID_1283_PG20)
+               if (ret < 0)
+                       return ret;
                ret = wl128x_cmd_radio_parms(wl);
-       else
+               if (ret < 0)
+                       return ret;
+       } else {
+               ret = wl1271_cmd_general_parms(wl);
+               if (ret < 0)
+                       return ret;
                ret = wl1271_cmd_radio_parms(wl);
-       if (ret < 0)
-               return ret;
+               if (ret < 0)
+                       return ret;
+               ret = wl1271_cmd_ext_radio_parms(wl);
+               if (ret < 0)
+                       return ret;
+       }
 
        /* Chip-specific init */
        ret = wl1271_chip_specific_init(wl);
@@ -707,11 +695,6 @@ int wl1271_hw_init(struct wl1271 *wl)
        if (ret < 0)
                goto out_free_memmap;
 
-       /* PHY layer config */
-       ret = wl1271_init_phy_config(wl);
-       if (ret < 0)
-               goto out_free_memmap;
-
        ret = wl1271_acx_dco_itrim_params(wl);
        if (ret < 0)
                goto out_free_memmap;
index 81140b81f654757b3b6d00588760ff6bc3ba23ad..2da0f404ef6e44df9c076b7e98b4d1c5ba53132d 100644 (file)
@@ -28,7 +28,6 @@
 
 int wl1271_hw_init_power_auth(struct wl1271 *wl);
 int wl1271_init_templates_config(struct wl1271 *wl);
-int wl1271_init_phy_config(struct wl1271 *wl);
 int wl1271_init_pta(struct wl1271 *wl);
 int wl1271_init_energy_detection(struct wl1271 *wl);
 int wl1271_chip_specific_init(struct wl1271 *wl);
index 2f7bfa86c8cd51e8256710ce10528119289acfcc..c3058419e227bb9bf35f5c91f94aeb9edbc3c24e 100644 (file)
@@ -674,11 +674,6 @@ static int wl1271_plt_init(struct wl1271 *wl)
        if (ret < 0)
                return ret;
 
-       /* PHY layer config */
-       ret = wl1271_init_phy_config(wl);
-       if (ret < 0)
-               goto out_free_memmap;
-
        ret = wl12xx_acx_mem_cfg(wl);
        if (ret < 0)
                goto out_free_memmap;
@@ -1448,7 +1443,7 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
        if (hlid == WL12XX_INVALID_LINK_ID ||
            (wlvif && !test_bit(hlid, wlvif->links_map))) {
                wl1271_debug(DEBUG_TX, "DROP skb hlid %d q %d", hlid, q);
-               dev_kfree_skb(skb);
+               ieee80211_free_txskb(hw, skb);
                goto out;
        }
 
@@ -1585,24 +1580,24 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl,
 
                ret = wait_for_completion_timeout(
                        &compl, msecs_to_jiffies(WL1271_PS_COMPLETE_TIMEOUT));
+
+               mutex_lock(&wl->mutex);
                if (ret <= 0) {
                        wl1271_warning("couldn't enter ps mode!");
                        ret = -EBUSY;
-                       goto out;
+                       goto out_cleanup;
                }
 
-               /* take mutex again, and wakeup */
-               mutex_lock(&wl->mutex);
-
                ret = wl1271_ps_elp_wakeup(wl);
                if (ret < 0)
-                       goto out_unlock;
+                       goto out_cleanup;
        }
 out_sleep:
        wl1271_ps_elp_sleep(wl);
+out_cleanup:
+       wlvif->ps_compl = NULL;
 out_unlock:
        mutex_unlock(&wl->mutex);
-out:
        return ret;
 
 }
index 8c277c0cb3728fb06ccd70176b77dea7a7af5e61..4fbd2a722ffabf28eb4f3c383490b2060c1535dc 100644 (file)
@@ -258,8 +258,12 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
                                                  wl->aggr_buf + pkt_offset,
                                                  pkt_length, unaligned,
                                                  &hlid) == 1) {
-                               WARN_ON(hlid >= WL12XX_MAX_LINKS);
-                               __set_bit(hlid, active_hlids);
+                               if (hlid < WL12XX_MAX_LINKS)
+                                       __set_bit(hlid, active_hlids);
+                               else
+                                       WARN(1,
+                                            "hlid exceeded WL12XX_MAX_LINKS "
+                                            "(%d)\n", hlid);
                        }
 
                        wl->rx_counter++;
index 978cf2de713dce858d45cfef119eace285a0c37e..25093c0cb0edf654ad04f603e3c1b7eb47603a1b 100644 (file)
@@ -38,6 +38,7 @@ enum wl1271_tm_commands {
        WL1271_TM_CMD_TEST,
        WL1271_TM_CMD_INTERROGATE,
        WL1271_TM_CMD_CONFIGURE,
+       WL1271_TM_CMD_NVS_PUSH,         /* Not in use. Keep to not break ABI */
        WL1271_TM_CMD_SET_PLT_MODE,
        WL1271_TM_CMD_RECOVER,
 
index 7d727ee6ddf6216228af8f13bce9b3e710905ecb..4508ccd78328017b173215fbfec69ea3a6c5c413 100644 (file)
@@ -740,7 +740,14 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
                        set_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags);
                        goto out_ack;
                } else if (ret < 0) {
-                       dev_kfree_skb(skb);
+                       if (wl12xx_is_dummy_packet(wl, skb))
+                               /*
+                                * fw still expects dummy packet,
+                                * so re-enqueue it
+                                */
+                               wl1271_skb_queue_head(wl, wlvif, skb);
+                       else
+                               ieee80211_free_txskb(wl->hw, skb);
                        goto out_ack;
                }
                buf_offset += ret;
index f1c911774bfd8637c21c041920cffd99cf6a7201..d21f71ff6f64c9326d0719b34e567740b609a54c 100644 (file)
 #include "conf.h"
 #include "ini.h"
 
-/*
- * FW versions support BA 11n
- * versions marks x.x.x.50-60.x
- */
-#define WL12XX_BA_SUPPORT_FW_COST_VER2_START    50
-#define WL12XX_BA_SUPPORT_FW_COST_VER2_END      60
-
 #define WL127X_FW_NAME "ti-connectivity/wl127x-fw-3.bin"
 #define WL128X_FW_NAME "ti-connectivity/wl128x-fw-3.bin"
 
index dbf214ef7321f3688b0e92e1458efc14713e1b20..b8b6c2abbd4a277f763bf6179f06d2943a656f9e 100644 (file)
@@ -72,6 +72,7 @@ MODULE_DEVICE_TABLE(usb, pn533_table);
 #define PN533_CMD_IN_LIST_PASSIVE_TARGET 0x4A
 #define PN533_CMD_IN_ATR 0x50
 #define PN533_CMD_IN_RELEASE 0x52
+#define PN533_CMD_IN_JUMP_FOR_DEP 0x56
 
 #define PN533_CMD_RESPONSE(cmd) (cmd + 1)
 
@@ -231,6 +232,26 @@ struct pn533_cmd_activate_response {
        u8 gt[];
 } __packed;
 
+/* PN533_CMD_IN_JUMP_FOR_DEP */
+struct pn533_cmd_jump_dep {
+       u8 active;
+       u8 baud;
+       u8 next;
+       u8 gt[];
+} __packed;
+
+struct pn533_cmd_jump_dep_response {
+       u8 status;
+       u8 tg;
+       u8 nfcid3t[10];
+       u8 didt;
+       u8 bst;
+       u8 brt;
+       u8 to;
+       u8 ppt;
+       /* optional */
+       u8 gt[];
+} __packed;
 
 struct pn533 {
        struct usb_device *udev;
@@ -1121,6 +1142,7 @@ static int pn533_activate_target_nfcdep(struct pn533 *dev)
 {
        struct pn533_cmd_activate_param param;
        struct pn533_cmd_activate_response *resp;
+       u16 gt_len;
        int rc;
 
        nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
@@ -1146,7 +1168,11 @@ static int pn533_activate_target_nfcdep(struct pn533 *dev)
        if (rc != PN533_CMD_RET_SUCCESS)
                return -EIO;
 
-       return 0;
+       /* ATR_RES general bytes are located at offset 16 */
+       gt_len = PN533_FRAME_CMD_PARAMS_LEN(dev->in_frame) - 16;
+       rc = nfc_set_remote_general_bytes(dev->nfc_dev, resp->gt, gt_len);
+
+       return rc;
 }
 
 static int pn533_activate_target(struct nfc_dev *nfc_dev, u32 target_idx,
@@ -1239,6 +1265,142 @@ static void pn533_deactivate_target(struct nfc_dev *nfc_dev, u32 target_idx)
        return;
 }
 
+
+static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg,
+                                               u8 *params, int params_len)
+{
+       struct pn533_cmd_jump_dep *cmd;
+       struct pn533_cmd_jump_dep_response *resp;
+       struct nfc_target nfc_target;
+       u8 target_gt_len;
+       int rc;
+
+       if (params_len == -ENOENT) {
+               nfc_dev_dbg(&dev->interface->dev, "");
+               return 0;
+       }
+
+       if (params_len < 0) {
+               nfc_dev_err(&dev->interface->dev,
+                               "Error %d when bringing DEP link up",
+                                                               params_len);
+               return 0;
+       }
+
+       if (dev->tgt_available_prots &&
+           !(dev->tgt_available_prots & (1 << NFC_PROTO_NFC_DEP))) {
+               nfc_dev_err(&dev->interface->dev,
+                       "The target does not support DEP");
+               return -EINVAL;
+       }
+
+       resp = (struct pn533_cmd_jump_dep_response *) params;
+       cmd = (struct pn533_cmd_jump_dep *) arg;
+       rc = resp->status & PN533_CMD_RET_MASK;
+       if (rc != PN533_CMD_RET_SUCCESS) {
+               nfc_dev_err(&dev->interface->dev,
+                               "Bringing DEP link up failed %d", rc);
+               return 0;
+       }
+
+       if (!dev->tgt_available_prots) {
+               nfc_dev_dbg(&dev->interface->dev, "Creating new target");
+
+               nfc_target.supported_protocols = NFC_PROTO_NFC_DEP_MASK;
+               rc = nfc_targets_found(dev->nfc_dev, &nfc_target, 1);
+               if (rc)
+                       return 0;
+
+               dev->tgt_available_prots = 0;
+       }
+
+       dev->tgt_active_prot = NFC_PROTO_NFC_DEP;
+
+       /* ATR_RES general bytes are located at offset 17 */
+       target_gt_len = PN533_FRAME_CMD_PARAMS_LEN(dev->in_frame) - 17;
+       rc = nfc_set_remote_general_bytes(dev->nfc_dev,
+                                               resp->gt, target_gt_len);
+       if (rc == 0)
+               rc = nfc_dep_link_is_up(dev->nfc_dev,
+                                               dev->nfc_dev->targets[0].idx,
+                                               !cmd->active, NFC_RF_INITIATOR);
+
+       return 0;
+}
+
+static int pn533_dep_link_up(struct nfc_dev *nfc_dev, int target_idx,
+                                               u8 comm_mode, u8 rf_mode)
+{
+       struct pn533 *dev = nfc_get_drvdata(nfc_dev);
+       struct pn533_cmd_jump_dep *cmd;
+       u8 cmd_len, local_gt_len, *local_gt;
+       int rc;
+
+       nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+
+       if (rf_mode == NFC_RF_TARGET) {
+               nfc_dev_err(&dev->interface->dev, "Target mode not supported");
+               return -EOPNOTSUPP;
+       }
+
+
+       if (dev->poll_mod_count) {
+               nfc_dev_err(&dev->interface->dev,
+                               "Cannot bring the DEP link up while polling");
+               return -EBUSY;
+       }
+
+       if (dev->tgt_active_prot) {
+               nfc_dev_err(&dev->interface->dev,
+                               "There is already an active target");
+               return -EBUSY;
+       }
+
+       local_gt = nfc_get_local_general_bytes(dev->nfc_dev, &local_gt_len);
+       if (local_gt_len > NFC_MAX_GT_LEN)
+               return -EINVAL;
+
+       cmd_len = sizeof(struct pn533_cmd_jump_dep) + local_gt_len;
+       cmd = kzalloc(cmd_len, GFP_KERNEL);
+       if (cmd == NULL)
+               return -ENOMEM;
+
+       pn533_tx_frame_init(dev->out_frame, PN533_CMD_IN_JUMP_FOR_DEP);
+
+       cmd->active = !comm_mode;
+       cmd->baud = 0;
+       if (local_gt != NULL) {
+               cmd->next = 4; /* We have some Gi */
+               memcpy(cmd->gt, local_gt, local_gt_len);
+       } else {
+               cmd->next = 0;
+       }
+
+       memcpy(PN533_FRAME_CMD_PARAMS_PTR(dev->out_frame), cmd, cmd_len);
+       dev->out_frame->datalen += cmd_len;
+
+       pn533_tx_frame_finish(dev->out_frame);
+
+       rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame,
+                               dev->in_maxlen, pn533_in_dep_link_up_complete,
+                               cmd, GFP_KERNEL);
+       if (rc)
+               goto out;
+
+
+out:
+       kfree(cmd);
+
+       return rc;
+}
+
+static int pn533_dep_link_down(struct nfc_dev *nfc_dev)
+{
+       pn533_deactivate_target(nfc_dev, 0);
+
+       return 0;
+}
+
 #define PN533_CMD_DATAEXCH_HEAD_LEN (sizeof(struct pn533_frame) + 3)
 #define PN533_CMD_DATAEXCH_DATA_MAXLEN 262
 
@@ -1368,7 +1530,7 @@ static int pn533_data_exchange(struct nfc_dev *nfc_dev, u32 target_idx,
                        PN533_CMD_DATAEXCH_DATA_MAXLEN +
                        PN533_FRAME_TAIL_SIZE;
 
-       skb_resp = nfc_alloc_skb(skb_resp_len, GFP_KERNEL);
+       skb_resp = nfc_alloc_recv_skb(skb_resp_len, GFP_KERNEL);
        if (!skb_resp) {
                rc = -ENOMEM;
                goto error;
@@ -1434,6 +1596,8 @@ static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata,
 struct nfc_ops pn533_nfc_ops = {
        .dev_up = NULL,
        .dev_down = NULL,
+       .dep_link_up = pn533_dep_link_up,
+       .dep_link_down = pn533_dep_link_down,
        .start_poll = pn533_start_poll,
        .stop_poll = pn533_stop_poll,
        .activate_target = pn533_activate_target,
index 34c3bab90b9a1e6a9e5f0032c207d16fc86ef21c..973223f5de8ebbeee690da524d0cf94c2593ce85 100644 (file)
@@ -607,6 +607,29 @@ static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
        memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24,
               sizeof(out->antenna_gain.ghz5));
 
+       /* Extract FEM info */
+       SPEX(fem.ghz2.tssipos, SSB_SPROM8_FEM2G,
+               SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT);
+       SPEX(fem.ghz2.extpa_gain, SSB_SPROM8_FEM2G,
+               SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
+       SPEX(fem.ghz2.pdet_range, SSB_SPROM8_FEM2G,
+               SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT);
+       SPEX(fem.ghz2.tr_iso, SSB_SPROM8_FEM2G,
+               SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT);
+       SPEX(fem.ghz2.antswlut, SSB_SPROM8_FEM2G,
+               SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
+
+       SPEX(fem.ghz5.tssipos, SSB_SPROM8_FEM5G,
+               SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT);
+       SPEX(fem.ghz5.extpa_gain, SSB_SPROM8_FEM5G,
+               SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
+       SPEX(fem.ghz5.pdet_range, SSB_SPROM8_FEM5G,
+               SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT);
+       SPEX(fem.ghz5.tr_iso, SSB_SPROM8_FEM5G,
+               SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT);
+       SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G,
+               SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
+
        sprom_extract_r458(out, in);
 
        /* TODO - get remaining rev 8 stuff needed */
index 4d4b59de9467116ce34b19846b061db56a2a2a7c..f4b8346b1a331f90fc9f29431b84b9176e4e6acb 100644 (file)
@@ -205,61 +205,82 @@ struct bcma_bus {
        struct ssb_sprom sprom;
 };
 
-extern inline u32 bcma_read8(struct bcma_device *core, u16 offset)
+static inline u32 bcma_read8(struct bcma_device *core, u16 offset)
 {
        return core->bus->ops->read8(core, offset);
 }
-extern inline u32 bcma_read16(struct bcma_device *core, u16 offset)
+static inline u32 bcma_read16(struct bcma_device *core, u16 offset)
 {
        return core->bus->ops->read16(core, offset);
 }
-extern inline u32 bcma_read32(struct bcma_device *core, u16 offset)
+static inline u32 bcma_read32(struct bcma_device *core, u16 offset)
 {
        return core->bus->ops->read32(core, offset);
 }
-extern inline
+static inline
 void bcma_write8(struct bcma_device *core, u16 offset, u32 value)
 {
        core->bus->ops->write8(core, offset, value);
 }
-extern inline
+static inline
 void bcma_write16(struct bcma_device *core, u16 offset, u32 value)
 {
        core->bus->ops->write16(core, offset, value);
 }
-extern inline
+static inline
 void bcma_write32(struct bcma_device *core, u16 offset, u32 value)
 {
        core->bus->ops->write32(core, offset, value);
 }
 #ifdef CONFIG_BCMA_BLOCKIO
-extern inline void bcma_block_read(struct bcma_device *core, void *buffer,
+static inline void bcma_block_read(struct bcma_device *core, void *buffer,
                                   size_t count, u16 offset, u8 reg_width)
 {
        core->bus->ops->block_read(core, buffer, count, offset, reg_width);
 }
-extern inline void bcma_block_write(struct bcma_device *core, const void *buffer,
-                                   size_t count, u16 offset, u8 reg_width)
+static inline void bcma_block_write(struct bcma_device *core,
+                                   const void *buffer, size_t count,
+                                   u16 offset, u8 reg_width)
 {
        core->bus->ops->block_write(core, buffer, count, offset, reg_width);
 }
 #endif
-extern inline u32 bcma_aread32(struct bcma_device *core, u16 offset)
+static inline u32 bcma_aread32(struct bcma_device *core, u16 offset)
 {
        return core->bus->ops->aread32(core, offset);
 }
-extern inline
+static inline
 void bcma_awrite32(struct bcma_device *core, u16 offset, u32 value)
 {
        core->bus->ops->awrite32(core, offset, value);
 }
 
-#define bcma_mask32(cc, offset, mask) \
-       bcma_write32(cc, offset, bcma_read32(cc, offset) & (mask))
-#define bcma_set32(cc, offset, set) \
-       bcma_write32(cc, offset, bcma_read32(cc, offset) | (set))
-#define bcma_maskset32(cc, offset, mask, set) \
-       bcma_write32(cc, offset, (bcma_read32(cc, offset) & (mask)) | (set))
+static inline void bcma_mask32(struct bcma_device *cc, u16 offset, u32 mask)
+{
+       bcma_write32(cc, offset, bcma_read32(cc, offset) & mask);
+}
+static inline void bcma_set32(struct bcma_device *cc, u16 offset, u32 set)
+{
+       bcma_write32(cc, offset, bcma_read32(cc, offset) | set);
+}
+static inline void bcma_maskset32(struct bcma_device *cc,
+                                 u16 offset, u32 mask, u32 set)
+{
+       bcma_write32(cc, offset, (bcma_read32(cc, offset) & mask) | set);
+}
+static inline void bcma_mask16(struct bcma_device *cc, u16 offset, u16 mask)
+{
+       bcma_write16(cc, offset, bcma_read16(cc, offset) & mask);
+}
+static inline void bcma_set16(struct bcma_device *cc, u16 offset, u16 set)
+{
+       bcma_write16(cc, offset, bcma_read16(cc, offset) | set);
+}
+static inline void bcma_maskset16(struct bcma_device *cc,
+                                 u16 offset, u16 mask, u16 set)
+{
+       bcma_write16(cc, offset, (bcma_read16(cc, offset) & mask) | set);
+}
 
 extern bool bcma_core_is_enabled(struct bcma_device *core);
 extern void bcma_core_disable(struct bcma_device *core, u32 flags);
index 1526d965ed064d864fb9c38db5d4067b8dd7bbe0..a33086a7530bc708e9b903723cd80a8967d429e7 100644 (file)
 #define BCMA_CC_PMU_CTL                        0x0600 /* PMU control */
 #define  BCMA_CC_PMU_CTL_ILP_DIV       0xFFFF0000 /* ILP div mask */
 #define  BCMA_CC_PMU_CTL_ILP_DIV_SHIFT 16
+#define  BCMA_CC_PMU_CTL_PLL_UPD       0x00000400
 #define  BCMA_CC_PMU_CTL_NOILPONW      0x00000200 /* No ILP on wait */
 #define  BCMA_CC_PMU_CTL_HTREQEN       0x00000100 /* HT req enable */
 #define  BCMA_CC_PMU_CTL_ALPREQEN      0x00000080 /* ALP req enable */
index 17f2a768e2ada1676fed7e1a76f7d06978f131ba..210e2c3255342f7cf6546ca0e1718fe6dc0e2dd4 100644 (file)
@@ -544,6 +544,15 @@ static inline int ieee80211_is_qos_nullfunc(__le16 fc)
               cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC);
 }
 
+/**
+ * ieee80211_is_first_frag - check if IEEE80211_SCTL_FRAG is not set
+ * @seq_ctrl: frame sequence control bytes in little-endian byteorder
+ */
+static inline int ieee80211_is_first_frag(__le16 seq_ctrl)
+{
+       return (seq_ctrl & cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0;
+}
+
 struct ieee80211s_hdr {
        u8 flags;
        u8 ttl;
index 36cb955b05cc517fc09ffcb0126571f7ccb5bcc0..89fee4ab1904784e7c748a1cbcb95fb053c9e36b 100644 (file)
@@ -62,6 +62,8 @@ enum nfc_commands {
        NFC_CMD_GET_DEVICE,
        NFC_CMD_DEV_UP,
        NFC_CMD_DEV_DOWN,
+       NFC_CMD_DEP_LINK_UP,
+       NFC_CMD_DEP_LINK_DOWN,
        NFC_CMD_START_POLL,
        NFC_CMD_STOP_POLL,
        NFC_CMD_GET_TARGET,
@@ -86,6 +88,8 @@ enum nfc_commands {
  * @NFC_ATTR_TARGET_SENS_RES: NFC-A targets extra information such as NFCID
  * @NFC_ATTR_TARGET_SEL_RES: NFC-A targets extra information (useful if the
  *     target is not NFC-Forum compliant)
+ * @NFC_ATTR_COMM_MODE: Passive or active mode
+ * @NFC_ATTR_RF_MODE: Initiator or target
  */
 enum nfc_attrs {
        NFC_ATTR_UNSPEC,
@@ -95,6 +99,8 @@ enum nfc_attrs {
        NFC_ATTR_TARGET_INDEX,
        NFC_ATTR_TARGET_SENS_RES,
        NFC_ATTR_TARGET_SEL_RES,
+       NFC_ATTR_COMM_MODE,
+       NFC_ATTR_RF_MODE,
 /* private: internal use only */
        __NFC_ATTR_AFTER_LAST
 };
@@ -111,6 +117,14 @@ enum nfc_attrs {
 
 #define NFC_PROTO_MAX          6
 
+/* NFC communication modes */
+#define NFC_COMM_ACTIVE  0
+#define NFC_COMM_PASSIVE 1
+
+/* NFC RF modes */
+#define NFC_RF_INITIATOR 0
+#define NFC_RF_TARGET    1
+
 /* NFC protocols masks used in bitsets */
 #define NFC_PROTO_JEWEL_MASK   (1 << NFC_PROTO_JEWEL)
 #define NFC_PROTO_MIFARE_MASK  (1 << NFC_PROTO_MIFARE)
@@ -125,9 +139,22 @@ struct sockaddr_nfc {
        __u32 nfc_protocol;
 };
 
+#define NFC_LLCP_MAX_SERVICE_NAME 63
+struct sockaddr_nfc_llcp {
+       sa_family_t sa_family;
+       __u32 dev_idx;
+       __u32 target_idx;
+       __u32 nfc_protocol;
+       __u8 dsap; /* Destination SAP, if known */
+       __u8 ssap; /* Source SAP to be bound to */
+       char service_name[NFC_LLCP_MAX_SERVICE_NAME]; /* Service name URI */;
+       size_t service_name_len;
+};
+
 /* NFC socket protocols */
 #define NFC_SOCKPROTO_RAW      0
-#define NFC_SOCKPROTO_MAX      1
+#define NFC_SOCKPROTO_LLCP     1
+#define NFC_SOCKPROTO_MAX      2
 
 #define NFC_HEADER_SIZE 1
 
index a18760684fc90628420e339e3215b9ff3d0a5eb4..f795cb7dccdda2011b62b1ea63f5d0d5ccc87143 100644 (file)
@@ -1536,7 +1536,11 @@ enum nl80211_iftype {
  * @NL80211_STA_FLAG_WME: station is WME/QoS capable
  * @NL80211_STA_FLAG_MFP: station uses management frame protection
  * @NL80211_STA_FLAG_AUTHENTICATED: station is authenticated
- * @NL80211_STA_FLAG_TDLS_PEER: station is a TDLS peer
+ * @NL80211_STA_FLAG_TDLS_PEER: station is a TDLS peer -- this flag should
+ *     only be used in managed mode (even in the flags mask). Note that the
+ *     flag can't be changed, it is only valid while adding a station, and
+ *     attempts to change it will silently be ignored (rather than rejected
+ *     as errors.)
  * @NL80211_STA_FLAG_MAX: highest station flag number currently defined
  * @__NL80211_STA_FLAG_AFTER_LAST: internal use
  */
index 061e560251b4d24a3177ace483b6d9e24e5a8411..dcf35b0f303aabef3698b0f7b06d4568748b87fb 100644 (file)
@@ -94,6 +94,15 @@ struct ssb_sprom {
                } ghz5;         /* 5GHz band */
        } antenna_gain;
 
+       struct {
+               struct {
+                       u8 tssipos, extpa_gain, pdet_range, tr_iso, antswlut;
+               } ghz2;
+               struct {
+                       u8 tssipos, extpa_gain, pdet_range, tr_iso, antswlut;
+               } ghz5;
+       } fem;
+
        /* TODO - add any parameters needed from rev 2, 3, 4, 5 or 8 SPROMs */
 };
 
index 98941203a27f248cf8215f998d17e15e12aed598..c814ae6eeb2292df3cb8080b0a10bf04726418fd 100644 (file)
 #define  SSB_SPROM8_RXPO2G             0x00FF  /* 2GHz RX power offset */
 #define  SSB_SPROM8_RXPO5G             0xFF00  /* 5GHz RX power offset */
 #define  SSB_SPROM8_RXPO5G_SHIFT       8
+#define SSB_SPROM8_FEM2G               0x00AE
+#define SSB_SPROM8_FEM5G               0x00B0
+#define  SSB_SROM8_FEM_TSSIPOS         0x0001
+#define  SSB_SROM8_FEM_TSSIPOS_SHIFT   0
+#define  SSB_SROM8_FEM_EXTPA_GAIN      0x0006
+#define  SSB_SROM8_FEM_EXTPA_GAIN_SHIFT        1
+#define  SSB_SROM8_FEM_PDET_RANGE      0x00F8
+#define  SSB_SROM8_FEM_PDET_RANGE_SHIFT        3
+#define  SSB_SROM8_FEM_TR_ISO          0x0700
+#define  SSB_SROM8_FEM_TR_ISO_SHIFT    8
+#define  SSB_SROM8_FEM_ANTSWLUT                0xF800
+#define  SSB_SROM8_FEM_ANTSWLUT_SHIFT  11
+#define SSB_SPROM8_THERMAL             0x00B2
+#define SSB_SPROM8_MPWR_RAWTS          0x00B4
+#define SSB_SPROM8_TS_SLP_OPT_CORRX    0x00B6
+#define SSB_SPROM8_FOC_HWIQ_IQSWP      0x00B8
+#define SSB_SPROM8_PHYCAL_TEMPDELTA    0x00BA
 #define SSB_SPROM8_MAXP_BG             0x00C0  /* Max Power 2GHz in path 1 */
 #define  SSB_SPROM8_MAXP_BG_MASK       0x00FF  /* Mask for Max Power 2GHz */
 #define  SSB_SPROM8_ITSSI_BG           0xFF00  /* Mask for path 1 itssi_bg */
index 3de1c39d03e5d62fd00d87a8fddcb0adc42098b1..9f85fca0b676606e0f04c4baa3a80bf6888778c4 100644 (file)
@@ -1346,7 +1346,12 @@ struct cfg80211_gtk_rekey_data {
  *
  * @add_station: Add a new station.
  * @del_station: Remove a station; @mac may be NULL to remove all stations.
- * @change_station: Modify a given station.
+ * @change_station: Modify a given station. Note that flags changes are not much
+ *     validated in cfg80211, in particular the auth/assoc/authorized flags
+ *     might come to the driver in invalid combinations -- make sure to check
+ *     them, also against the existing state! Also, supported_rates changes are
+ *     not checked in station mode -- drivers need to reject (or ignore) them
+ *     for anything but TDLS peers.
  * @get_station: get station information for the station identified by @mac
  * @dump_station: dump station callback -- resume dump at index @idx
  *
@@ -1694,7 +1699,9 @@ struct cfg80211_ops {
  *     regulatory domain no user regulatory domain can enable these channels
  *     at a later time. This can be used for devices which do not have
  *     calibration information guaranteed for frequencies or settings
- *     outside of its regulatory domain.
+ *     outside of its regulatory domain. If used in combination with
+ *     WIPHY_FLAG_CUSTOM_REGULATORY the inspected country IE power settings
+ *     will be followed.
  * @WIPHY_FLAG_DISABLE_BEACON_HINTS: enable this if your driver needs to ensure
  *     that passive scan flags and beaconing flags may not be lifted by
  *     cfg80211 due to regulatory beacon hints. For more information on beacon
@@ -3063,6 +3070,32 @@ void cfg80211_roamed(struct net_device *dev,
                     const u8 *req_ie, size_t req_ie_len,
                     const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp);
 
+/**
+ * cfg80211_roamed_bss - notify cfg80211 of roaming
+ *
+ * @dev: network device
+ * @bss: entry of bss to which STA got roamed
+ * @req_ie: association request IEs (maybe be %NULL)
+ * @req_ie_len: association request IEs length
+ * @resp_ie: association response IEs (may be %NULL)
+ * @resp_ie_len: assoc response IEs length
+ * @gfp: allocation flags
+ *
+ * This is just a wrapper to notify cfg80211 of roaming event with driver
+ * passing bss to avoid a race in timeout of the bss entry. It should be
+ * called by the underlying driver whenever it roamed from one AP to another
+ * while connected. Drivers which have roaming implemented in firmware
+ * may use this function to avoid a race in bss entry timeout where the bss
+ * entry of the new AP is seen in the driver, but gets timed out by the time
+ * it is accessed in __cfg80211_roamed() due to delay in scheduling
+ * rdev->event_work. In case of any failures, the reference is released
+ * either in cfg80211_roamed_bss() or in __cfg80211_romed(), Otherwise,
+ * it will be released while diconneting from the current bss.
+ */
+void cfg80211_roamed_bss(struct net_device *dev, struct cfg80211_bss *bss,
+                        const u8 *req_ie, size_t req_ie_len,
+                        const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp);
+
 /**
  * cfg80211_disconnected - notify cfg80211 that connection was dropped
  *
index 6a7f602aa841d87794fa175c7e3ca7d2d934d4c0..ccfe757a94ec2d17a16bb4d9424cd21510823800 100644 (file)
@@ -52,6 +52,9 @@ struct nfc_ops {
        int (*dev_down)(struct nfc_dev *dev);
        int (*start_poll)(struct nfc_dev *dev, u32 protocols);
        void (*stop_poll)(struct nfc_dev *dev);
+       int (*dep_link_up)(struct nfc_dev *dev, int target_idx,
+                               u8 comm_mode, u8 rf_mode);
+       int (*dep_link_down)(struct nfc_dev *dev);
        int (*activate_target)(struct nfc_dev *dev, u32 target_idx,
                                                        u32 protocol);
        void (*deactivate_target)(struct nfc_dev *dev, u32 target_idx);
@@ -60,6 +63,9 @@ struct nfc_ops {
                                                        void *cb_context);
 };
 
+#define NFC_TARGET_IDX_ANY -1
+#define NFC_MAX_GT_LEN 48
+
 struct nfc_target {
        u32 idx;
        u32 supported_protocols;
@@ -83,6 +89,8 @@ struct nfc_dev {
        bool dev_up;
        bool polling;
        bool remote_activated;
+       bool dep_link_up;
+       u32 dep_rf_mode;
        struct nfc_genl_data genl_data;
        u32 supported_protocols;
 
@@ -157,9 +165,20 @@ static inline const char *nfc_device_name(struct nfc_dev *dev)
        return dev_name(&dev->dev);
 }
 
-struct sk_buff *nfc_alloc_skb(unsigned int size, gfp_t gfp);
+struct sk_buff *nfc_alloc_send_skb(struct nfc_dev *dev, struct sock *sk,
+                                       unsigned int flags, unsigned int size,
+                                       unsigned int *err);
+struct sk_buff *nfc_alloc_recv_skb(unsigned int size, gfp_t gfp);
+
+int nfc_set_remote_general_bytes(struct nfc_dev *dev,
+                                       u8 *gt, u8 gt_len);
+
+u8 *nfc_get_local_general_bytes(struct nfc_dev *dev, u8 *gt_len);
 
 int nfc_targets_found(struct nfc_dev *dev, struct nfc_target *targets,
                                                        int ntargets);
 
+int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx,
+                      u8 comm_mode, u8 rf_mode);
+
 #endif /* __NET_NFC_H */
index 7380287f010ea90b6cf9556163e537ae711aac2b..e92f98d327462cde5b7761b33dd039ba4b935d7a 100644 (file)
@@ -55,6 +55,8 @@
  * @ampdu_action function will be called with the action
  * %IEEE80211_AMPDU_TX_STOP. In this case, the call must not fail,
  * and the driver must later call ieee80211_stop_tx_ba_cb_irqsafe().
+ * Note that the sta can get destroyed before the BA tear down is
+ * complete.
  */
 
 static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata,
@@ -105,7 +107,7 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata,
        mgmt->u.action.u.addba_req.start_seq_num =
                                        cpu_to_le16(start_seq_num << 4);
 
-       ieee80211_tx_skb(sdata, skb);
+       ieee80211_tx_skb_tid(sdata, skb, tid);
 }
 
 void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn)
@@ -134,7 +136,7 @@ void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn)
        bar->start_seq_num = cpu_to_le16(ssn);
 
        IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
-       ieee80211_tx_skb(sdata, skb);
+       ieee80211_tx_skb_tid(sdata, skb, tid);
 }
 EXPORT_SYMBOL(ieee80211_send_bar);
 
index 393b2a4445b8e26108ffb94dec3215a489175609..66ad9d9af87f8f8d13ef199fe8b366207194f9ed 100644 (file)
@@ -746,10 +746,11 @@ static void ieee80211_send_layer2_update(struct sta_info *sta)
        netif_rx_ni(skb);
 }
 
-static void sta_apply_parameters(struct ieee80211_local *local,
-                                struct sta_info *sta,
-                                struct station_parameters *params)
+static int sta_apply_parameters(struct ieee80211_local *local,
+                               struct sta_info *sta,
+                               struct station_parameters *params)
 {
+       int ret = 0;
        u32 rates;
        int i, j;
        struct ieee80211_supported_band *sband;
@@ -761,13 +762,59 @@ static void sta_apply_parameters(struct ieee80211_local *local,
        mask = params->sta_flags_mask;
        set = params->sta_flags_set;
 
+       /*
+        * In mesh mode, we can clear AUTHENTICATED flag but must
+        * also make ASSOCIATED follow appropriately for the driver
+        * API. See also below, after AUTHORIZED changes.
+        */
+       if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) {
+               /* cfg80211 should not allow this in non-mesh modes */
+               if (WARN_ON(!ieee80211_vif_is_mesh(&sdata->vif)))
+                       return -EINVAL;
+
+               if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED) &&
+                   !test_sta_flag(sta, WLAN_STA_AUTH)) {
+                       ret = sta_info_move_state_checked(sta,
+                                       IEEE80211_STA_AUTH);
+                       if (ret)
+                               return ret;
+                       ret = sta_info_move_state_checked(sta,
+                                       IEEE80211_STA_ASSOC);
+                       if (ret)
+                               return ret;
+               }
+       }
+
        if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
                if (set & BIT(NL80211_STA_FLAG_AUTHORIZED))
-                       set_sta_flag(sta, WLAN_STA_AUTHORIZED);
+                       ret = sta_info_move_state_checked(sta,
+                                       IEEE80211_STA_AUTHORIZED);
                else
-                       clear_sta_flag(sta, WLAN_STA_AUTHORIZED);
+                       ret = sta_info_move_state_checked(sta,
+                                       IEEE80211_STA_ASSOC);
+               if (ret)
+                       return ret;
        }
 
+       if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) {
+               /* cfg80211 should not allow this in non-mesh modes */
+               if (WARN_ON(!ieee80211_vif_is_mesh(&sdata->vif)))
+                       return -EINVAL;
+
+               if (!(set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) &&
+                   test_sta_flag(sta, WLAN_STA_AUTH)) {
+                       ret = sta_info_move_state_checked(sta,
+                                       IEEE80211_STA_AUTH);
+                       if (ret)
+                               return ret;
+                       ret = sta_info_move_state_checked(sta,
+                                       IEEE80211_STA_NONE);
+                       if (ret)
+                               return ret;
+               }
+       }
+
+
        if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) {
                if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE))
                        set_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE);
@@ -792,13 +839,6 @@ static void sta_apply_parameters(struct ieee80211_local *local,
                        clear_sta_flag(sta, WLAN_STA_MFP);
        }
 
-       if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) {
-               if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED))
-                       set_sta_flag(sta, WLAN_STA_AUTH);
-               else
-                       clear_sta_flag(sta, WLAN_STA_AUTH);
-       }
-
        if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
                if (set & BIT(NL80211_STA_FLAG_TDLS_PEER))
                        set_sta_flag(sta, WLAN_STA_TDLS_PEER);
@@ -870,6 +910,8 @@ static void sta_apply_parameters(struct ieee80211_local *local,
                        }
 #endif
        }
+
+       return 0;
 }
 
 static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
@@ -896,20 +938,18 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
        if (is_multicast_ether_addr(mac))
                return -EINVAL;
 
-       /* Only TDLS-supporting stations can add TDLS peers */
-       if ((params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) &&
-           !((wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) &&
-             sdata->vif.type == NL80211_IFTYPE_STATION))
-               return -ENOTSUPP;
-
        sta = sta_info_alloc(sdata, mac, GFP_KERNEL);
        if (!sta)
                return -ENOMEM;
 
-       set_sta_flag(sta, WLAN_STA_AUTH);
-       set_sta_flag(sta, WLAN_STA_ASSOC);
+       sta_info_move_state(sta, IEEE80211_STA_AUTH);
+       sta_info_move_state(sta, IEEE80211_STA_ASSOC);
 
-       sta_apply_parameters(local, sta, params);
+       err = sta_apply_parameters(local, sta, params);
+       if (err) {
+               sta_info_free(local, sta);
+               return err;
+       }
 
        /*
         * for TDLS, rate control should be initialized only when supported
@@ -960,19 +1000,19 @@ static int ieee80211_change_station(struct wiphy *wiphy,
        struct sta_info *sta;
        struct ieee80211_sub_if_data *vlansdata;
 
-       rcu_read_lock();
+       mutex_lock(&local->sta_mtx);
 
        sta = sta_info_get_bss(sdata, mac);
        if (!sta) {
-               rcu_read_unlock();
+               mutex_unlock(&local->sta_mtx);
                return -ENOENT;
        }
 
-       /* The TDLS bit cannot be toggled after the STA was added */
-       if ((params->sta_flags_mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) &&
-           !!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) !=
-           !!test_sta_flag(sta, WLAN_STA_TDLS_PEER)) {
-               rcu_read_unlock();
+       /* in station mode, supported rates are only valid with TDLS */
+       if (sdata->vif.type == NL80211_IFTYPE_STATION &&
+           params->supported_rates &&
+           !test_sta_flag(sta, WLAN_STA_TDLS_PEER)) {
+               mutex_unlock(&local->sta_mtx);
                return -EINVAL;
        }
 
@@ -981,13 +1021,13 @@ static int ieee80211_change_station(struct wiphy *wiphy,
 
                if (vlansdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
                    vlansdata->vif.type != NL80211_IFTYPE_AP) {
-                       rcu_read_unlock();
+                       mutex_unlock(&local->sta_mtx);
                        return -EINVAL;
                }
 
                if (params->vlan->ieee80211_ptr->use_4addr) {
                        if (vlansdata->u.vlan.sta) {
-                               rcu_read_unlock();
+                               mutex_unlock(&local->sta_mtx);
                                return -EBUSY;
                        }
 
@@ -1003,7 +1043,7 @@ static int ieee80211_change_station(struct wiphy *wiphy,
        if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) && params->supported_rates)
                rate_control_rate_init(sta);
 
-       rcu_read_unlock();
+       mutex_unlock(&local->sta_mtx);
 
        if (sdata->vif.type == NL80211_IFTYPE_STATION &&
            params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED))
index 8df28910b8ee9865d333d46773e67c250313bc20..176c08ffb13c50e5f5fa8c212175a8367f09bb97 100644 (file)
@@ -321,6 +321,7 @@ static ssize_t ieee80211_if_parse_tkip_mic_test(
 __IEEE80211_IF_FILE_W(tkip_mic_test);
 
 /* AP attributes */
+IEEE80211_IF_FILE(num_sta_authorized, u.ap.num_sta_authorized, ATOMIC);
 IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC);
 IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC);
 
@@ -458,6 +459,7 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata)
        DEBUGFS_ADD(rc_rateidx_mask_2ghz);
        DEBUGFS_ADD(rc_rateidx_mask_5ghz);
 
+       DEBUGFS_ADD(num_sta_authorized);
        DEBUGFS_ADD(num_sta_ps);
        DEBUGFS_ADD(dtim_count);
        DEBUGFS_ADD(num_buffered_multicast);
index 0fd9c2a7f242c33ee36391c9405d2721742494fa..f25fff7607d87049c2b9ec02b1cc4370d0124f3f 100644 (file)
@@ -300,7 +300,7 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,
        mgmt->u.action.u.delba.params = cpu_to_le16(params);
        mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code);
 
-       ieee80211_tx_skb(sdata, skb);
+       ieee80211_tx_skb_tid(sdata, skb, tid);
 }
 
 void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata,
index 3f830ac159e519f7fde25db5d51c4ff344f813ce..f8a32bf98216c1bb40dadf82bfa67153a349ec9f 100644 (file)
@@ -275,6 +275,80 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
                                  cbss->tsf);
 }
 
+static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta)
+       __acquires(RCU)
+{
+       struct ieee80211_sub_if_data *sdata = sta->sdata;
+       u8 addr[ETH_ALEN];
+
+       memcpy(addr, sta->sta.addr, ETH_ALEN);
+
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+       wiphy_debug(sdata->local->hw.wiphy,
+                   "Adding new IBSS station %pM (dev=%s)\n",
+                   addr, sdata->name);
+#endif
+
+       sta_info_move_state(sta, IEEE80211_STA_AUTH);
+       sta_info_move_state(sta, IEEE80211_STA_ASSOC);
+       sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
+
+       rate_control_rate_init(sta);
+
+       /* If it fails, maybe we raced another insertion? */
+       if (sta_info_insert_rcu(sta))
+               return sta_info_get(sdata, addr);
+       return sta;
+}
+
+static struct sta_info *
+ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
+                      const u8 *bssid, const u8 *addr,
+                      u32 supp_rates)
+       __acquires(RCU)
+{
+       struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
+       struct ieee80211_local *local = sdata->local;
+       struct sta_info *sta;
+       int band = local->hw.conf.channel->band;
+
+       /*
+        * XXX: Consider removing the least recently used entry and
+        *      allow new one to be added.
+        */
+       if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) {
+               if (net_ratelimit())
+                       printk(KERN_DEBUG "%s: No room for a new IBSS STA entry %pM\n",
+                              sdata->name, addr);
+               rcu_read_lock();
+               return NULL;
+       }
+
+       if (ifibss->state == IEEE80211_IBSS_MLME_SEARCH) {
+               rcu_read_lock();
+               return NULL;
+       }
+
+       if (compare_ether_addr(bssid, sdata->u.ibss.bssid)) {
+               rcu_read_lock();
+               return NULL;
+       }
+
+       sta = sta_info_alloc(sdata, addr, GFP_KERNEL);
+       if (!sta) {
+               rcu_read_lock();
+               return NULL;
+       }
+
+       sta->last_rx = jiffies;
+
+       /* make sure mandatory rates are always added */
+       sta->sta.supp_rates[band] = supp_rates |
+                       ieee80211_mandatory_rates(local, band);
+
+       return ieee80211_ibss_finish_sta(sta);
+}
+
 static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
                                  struct ieee80211_mgmt *mgmt,
                                  size_t len,
@@ -334,10 +408,11 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
 #endif
                                        rates_updated = true;
                                }
-                       } else
+                       } else {
+                               rcu_read_unlock();
                                sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid,
-                                               mgmt->sa, supp_rates,
-                                               GFP_ATOMIC);
+                                               mgmt->sa, supp_rates);
+                       }
                }
 
                if (sta && elems->wmm_info)
@@ -464,21 +539,17 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
                ieee80211_sta_join_ibss(sdata, bss);
                supp_rates = ieee80211_sta_get_rates(local, elems, band);
                ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa,
-                                      supp_rates, GFP_KERNEL);
+                                      supp_rates);
+               rcu_read_unlock();
        }
 
  put_bss:
        ieee80211_rx_bss_put(local, bss);
 }
 
-/*
- * Add a new IBSS station, will also be called by the RX code when,
- * in IBSS mode, receiving a frame from a yet-unknown station, hence
- * must be callable in atomic context.
- */
-struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
-                                       u8 *bssid, u8 *addr, u32 supp_rates,
-                                       gfp_t gfp)
+void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata,
+                             const u8 *bssid, const u8 *addr,
+                             u32 supp_rates)
 {
        struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
        struct ieee80211_local *local = sdata->local;
@@ -493,37 +564,29 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
                if (net_ratelimit())
                        printk(KERN_DEBUG "%s: No room for a new IBSS STA entry %pM\n",
                               sdata->name, addr);
-               return NULL;
+               return;
        }
 
        if (ifibss->state == IEEE80211_IBSS_MLME_SEARCH)
-               return NULL;
+               return;
 
        if (compare_ether_addr(bssid, sdata->u.ibss.bssid))
-               return NULL;
-
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-       wiphy_debug(local->hw.wiphy, "Adding new IBSS station %pM (dev=%s)\n",
-                   addr, sdata->name);
-#endif
+               return;
 
-       sta = sta_info_alloc(sdata, addr, gfp);
+       sta = sta_info_alloc(sdata, addr, GFP_ATOMIC);
        if (!sta)
-               return NULL;
+               return;
 
        sta->last_rx = jiffies;
-       set_sta_flag(sta, WLAN_STA_AUTHORIZED);
 
        /* make sure mandatory rates are always added */
        sta->sta.supp_rates[band] = supp_rates |
                        ieee80211_mandatory_rates(local, band);
 
-       rate_control_rate_init(sta);
-
-       /* If it fails, maybe we raced another insertion? */
-       if (sta_info_insert(sta))
-               return sta_info_get(sdata, addr);
-       return sta;
+       spin_lock(&ifibss->incomplete_lock);
+       list_add(&sta->list, &ifibss->incomplete_stations);
+       spin_unlock(&ifibss->incomplete_lock);
+       ieee80211_queue_work(&local->hw, &sdata->work);
 }
 
 static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata)
@@ -862,6 +925,7 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
 void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata)
 {
        struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
+       struct sta_info *sta;
 
        mutex_lock(&ifibss->mtx);
 
@@ -873,6 +937,19 @@ void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata)
        if (!ifibss->ssid_len)
                goto out;
 
+       spin_lock_bh(&ifibss->incomplete_lock);
+       while (!list_empty(&ifibss->incomplete_stations)) {
+               sta = list_first_entry(&ifibss->incomplete_stations,
+                                      struct sta_info, list);
+               list_del(&sta->list);
+               spin_unlock_bh(&ifibss->incomplete_lock);
+
+               ieee80211_ibss_finish_sta(sta);
+               rcu_read_unlock();
+               spin_lock_bh(&ifibss->incomplete_lock);
+       }
+       spin_unlock_bh(&ifibss->incomplete_lock);
+
        switch (ifibss->state) {
        case IEEE80211_IBSS_MLME_SEARCH:
                ieee80211_sta_find_ibss(sdata);
@@ -931,6 +1008,8 @@ void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata)
        setup_timer(&ifibss->timer, ieee80211_ibss_timer,
                    (unsigned long) sdata);
        mutex_init(&ifibss->mtx);
+       INIT_LIST_HEAD(&ifibss->incomplete_stations);
+       spin_lock_init(&ifibss->incomplete_lock);
 }
 
 /* scan finished notification */
@@ -993,8 +1072,11 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
        if (params->channel_fixed) {
                sdata->local->oper_channel = params->channel;
                if (!ieee80211_set_channel_type(sdata->local, sdata,
-                                              params->channel_type))
+                                              params->channel_type)) {
+                       mutex_unlock(&sdata->u.ibss.mtx);
+                       kfree_skb(skb);
                        return -EINVAL;
+               }
        }
 
        if (params->ie) {
@@ -1047,6 +1129,7 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
        struct cfg80211_bss *cbss;
        u16 capability;
        int active_ibss;
+       struct sta_info *sta;
 
        mutex_lock(&sdata->u.ibss.mtx);
 
@@ -1075,6 +1158,19 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
        }
 
        sta_info_flush(sdata->local, sdata);
+
+       spin_lock_bh(&ifibss->incomplete_lock);
+       while (!list_empty(&ifibss->incomplete_stations)) {
+               sta = list_first_entry(&ifibss->incomplete_stations,
+                                      struct sta_info, list);
+               list_del(&sta->list);
+               spin_unlock_bh(&ifibss->incomplete_lock);
+
+               sta_info_free(local, sta);
+               spin_lock_bh(&ifibss->incomplete_lock);
+       }
+       spin_unlock_bh(&ifibss->incomplete_lock);
+
        netif_carrier_off(sdata->dev);
 
        /* remove beacon */
index 96fe75410bbe09549929682d31a7756286869759..c3f3e431a573b4195f7d79f384cdf6d26090b1bb 100644 (file)
@@ -243,6 +243,7 @@ struct ieee80211_if_ap {
        u8 tim[sizeof(unsigned long) * BITS_TO_LONGS(IEEE80211_MAX_AID + 1)];
        struct sk_buff_head ps_bc_buf;
        atomic_t num_sta_ps; /* number of stations in PS mode */
+       atomic_t num_sta_authorized; /* number of authorized stations */
        int dtim_count;
        bool dtim_bc_mc;
 };
@@ -481,6 +482,9 @@ struct ieee80211_if_ibss {
        struct sk_buff __rcu *presp;
        struct sk_buff *skb;
 
+       spinlock_t incomplete_lock;
+       struct list_head incomplete_stations;
+
        enum {
                IEEE80211_IBSS_MLME_SEARCH,
                IEEE80211_IBSS_MLME_JOINED,
@@ -851,18 +855,15 @@ struct ieee80211_local {
 
        /* Station data */
        /*
-        * The mutex only protects the list and counter,
-        * reads are done in RCU.
-        * Additionally, the lock protects the hash table,
-        * the pending list and each BSS's TIM bitmap.
+        * The mutex only protects the list, hash table and
+        * counter, reads are done with RCU.
         */
        struct mutex sta_mtx;
-       spinlock_t sta_lock;
+       spinlock_t tim_lock;
        unsigned long num_sta;
-       struct list_head sta_list, sta_pending_list;
+       struct list_head sta_list;
        struct sta_info __rcu *sta_hash[STA_HASH_SIZE];
        struct timer_list sta_cleanup;
-       struct work_struct sta_finish_work;
        int sta_generation;
 
        struct sk_buff_head pending[IEEE80211_MAX_QUEUES];
@@ -1171,9 +1172,8 @@ void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata);
 /* IBSS code */
 void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local);
 void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata);
-struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
-                                       u8 *bssid, u8 *addr, u32 supp_rates,
-                                       gfp_t gfp);
+void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata,
+                             const u8 *bssid, const u8 *addr, u32 supp_rates);
 int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
                        struct cfg80211_ibss_params *params);
 int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata);
@@ -1349,7 +1349,16 @@ void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int ke
                                     gfp_t gfp);
 void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata);
 void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb);
-void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb);
+
+void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata,
+                         struct sk_buff *skb, int tid);
+static void inline ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata,
+                                   struct sk_buff *skb)
+{
+       /* Send all internal mgmt frames on VO. Accordingly set TID to 7. */
+       ieee80211_tx_skb_tid(sdata, skb, 7);
+}
+
 void ieee802_11_parse_elems(u8 *start, size_t len,
                            struct ieee802_11_elems *elems);
 u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
index 3d3bb5e9d8fac30e33756c03a23dab312549207f..e47768cb8cb3b18eb98e3e16abc542a3735ad9e3 100644 (file)
@@ -318,8 +318,9 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up)
                        goto err_del_interface;
                }
 
-               /* no atomic bitop required since STA is not live yet */
-               set_sta_flag(sta, WLAN_STA_AUTHORIZED);
+               sta_info_move_state(sta, IEEE80211_STA_AUTH);
+               sta_info_move_state(sta, IEEE80211_STA_ASSOC);
+               sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
 
                res = sta_info_insert(sta);
                if (res) {
index 60198ac664a006ac81b9106c6b9ccc4613260340..0a0d94ad9b08374fe90e0f653da4d4b352e8f6c9 100644 (file)
@@ -47,7 +47,7 @@ void ieee80211_configure_filter(struct ieee80211_local *local)
        if (atomic_read(&local->iff_allmultis))
                new_flags |= FIF_ALLMULTI;
 
-       if (local->monitors || local->scanning)
+       if (local->monitors || test_bit(SCAN_SW_SCANNING, &local->scanning))
                new_flags |= FIF_BCN_PRBRESP_PROMISC;
 
        if (local->fif_probe_req || local->probe_req_reg)
@@ -150,8 +150,8 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
                changed |= IEEE80211_CONF_CHANGE_SMPS;
        }
 
-       if ((local->scanning & SCAN_SW_SCANNING) ||
-           (local->scanning & SCAN_HW_SCANNING))
+       if (test_bit(SCAN_SW_SCANNING, &local->scanning) ||
+           test_bit(SCAN_HW_SCANNING, &local->scanning))
                power = chan->max_power;
        else
                power = local->power_constr_level ?
@@ -393,9 +393,6 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
        sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
        bss_conf = &sdata->vif.bss_conf;
 
-       if (!ieee80211_sdata_running(sdata))
-               return NOTIFY_DONE;
-
        /* ARP filtering is only supported in managed mode */
        if (sdata->vif.type != NL80211_IFTYPE_STATION)
                return NOTIFY_DONE;
@@ -424,7 +421,7 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
        }
        bss_conf->arp_addr_cnt = c;
 
-       /* Configure driver only if associated */
+       /* Configure driver only if associated (which also implies it is up) */
        if (ifmgd->associated) {
                bss_conf->arp_filter_enabled = sdata->arp_filter_state;
                ieee80211_bss_info_change_notify(sdata,
index 7314372b12ba2eb2096a749737ae05434be2e8bb..41ef1b4764422a85d56334f16c320b8d1d4db292 100644 (file)
@@ -96,9 +96,12 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
        if (!sta)
                return NULL;
 
-       set_sta_flag(sta, WLAN_STA_AUTH);
-       set_sta_flag(sta, WLAN_STA_AUTHORIZED);
+       sta_info_move_state(sta, IEEE80211_STA_AUTH);
+       sta_info_move_state(sta, IEEE80211_STA_ASSOC);
+       sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
+
        set_sta_flag(sta, WLAN_STA_WME);
+
        sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
        if (elems->ht_cap_elem)
                ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
index 09019d135942af5042175b0955a6147af464e84d..a984f1f60ddbc7ab0370ce3665415260f2a7ef2e 100644 (file)
@@ -819,7 +819,7 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
        }
 
        if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) &&
-           (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED))) {
+           !(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED)) {
                netif_tx_stop_all_queues(sdata->dev);
 
                if (drv_tx_frames_pending(local))
@@ -1577,10 +1577,10 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
                return false;
        }
 
-       set_sta_flag(sta, WLAN_STA_AUTH);
-       set_sta_flag(sta, WLAN_STA_ASSOC);
+       sta_info_move_state(sta, IEEE80211_STA_AUTH);
+       sta_info_move_state(sta, IEEE80211_STA_ASSOC);
        if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT))
-               set_sta_flag(sta, WLAN_STA_AUTHORIZED);
+               sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
 
        rates = 0;
        basic_rates = 0;
@@ -2371,6 +2371,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
                    (unsigned long) sdata);
 
        ifmgd->flags = 0;
+       ifmgd->powersave = sdata->wdev.ps;
 
        mutex_init(&ifmgd->mtx);
 
index 7d226417ef46286753351db476db1ebaf6b90f1c..2be5b7d69ad71aea6c33e65e20e6441703ff8211 100644 (file)
@@ -2775,8 +2775,8 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx,
                                rate_idx = 0; /* TODO: HT rates */
                        else
                                rate_idx = status->rate_idx;
-                       rx->sta = ieee80211_ibss_add_sta(sdata, bssid,
-                                       hdr->addr2, BIT(rate_idx), GFP_ATOMIC);
+                       ieee80211_ibss_rx_no_sta(sdata, bssid, hdr->addr2,
+                                                BIT(rate_idx));
                }
                break;
        case NL80211_IFTYPE_MESH_POINT:
index f98235262006d77815022e85bffd319e3b125883..2db01e9541e7ea579ebde1ef8370f75e646c0320 100644 (file)
  * freed before they are done using it.
  */
 
-/* Caller must hold local->sta_lock */
+/* Caller must hold local->sta_mtx */
 static int sta_info_hash_del(struct ieee80211_local *local,
                             struct sta_info *sta)
 {
        struct sta_info *s;
 
        s = rcu_dereference_protected(local->sta_hash[STA_HASH(sta->sta.addr)],
-                                     lockdep_is_held(&local->sta_lock));
+                                     lockdep_is_held(&local->sta_mtx));
        if (!s)
                return -ENOENT;
        if (s == sta) {
@@ -81,7 +81,7 @@ static int sta_info_hash_del(struct ieee80211_local *local,
        while (rcu_access_pointer(s->hnext) &&
               rcu_access_pointer(s->hnext) != sta)
                s = rcu_dereference_protected(s->hnext,
-                                       lockdep_is_held(&local->sta_lock));
+                                       lockdep_is_held(&local->sta_mtx));
        if (rcu_access_pointer(s->hnext)) {
                RCU_INIT_POINTER(s->hnext, sta->hnext);
                return 0;
@@ -98,14 +98,12 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
        struct sta_info *sta;
 
        sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)],
-                                   lockdep_is_held(&local->sta_lock) ||
                                    lockdep_is_held(&local->sta_mtx));
        while (sta) {
                if (sta->sdata == sdata && !sta->dummy &&
                    memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
                        break;
                sta = rcu_dereference_check(sta->hnext,
-                                           lockdep_is_held(&local->sta_lock) ||
                                            lockdep_is_held(&local->sta_mtx));
        }
        return sta;
@@ -119,14 +117,12 @@ struct sta_info *sta_info_get_rx(struct ieee80211_sub_if_data *sdata,
        struct sta_info *sta;
 
        sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)],
-                                   lockdep_is_held(&local->sta_lock) ||
                                    lockdep_is_held(&local->sta_mtx));
        while (sta) {
                if (sta->sdata == sdata &&
                    memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
                        break;
                sta = rcu_dereference_check(sta->hnext,
-                                           lockdep_is_held(&local->sta_lock) ||
                                            lockdep_is_held(&local->sta_mtx));
        }
        return sta;
@@ -143,7 +139,6 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,
        struct sta_info *sta;
 
        sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)],
-                                   lockdep_is_held(&local->sta_lock) ||
                                    lockdep_is_held(&local->sta_mtx));
        while (sta) {
                if ((sta->sdata == sdata ||
@@ -152,7 +147,6 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,
                    memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
                        break;
                sta = rcu_dereference_check(sta->hnext,
-                                           lockdep_is_held(&local->sta_lock) ||
                                            lockdep_is_held(&local->sta_mtx));
        }
        return sta;
@@ -169,7 +163,6 @@ struct sta_info *sta_info_get_bss_rx(struct ieee80211_sub_if_data *sdata,
        struct sta_info *sta;
 
        sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)],
-                                   lockdep_is_held(&local->sta_lock) ||
                                    lockdep_is_held(&local->sta_mtx));
        while (sta) {
                if ((sta->sdata == sdata ||
@@ -177,7 +170,6 @@ struct sta_info *sta_info_get_bss_rx(struct ieee80211_sub_if_data *sdata,
                    memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
                        break;
                sta = rcu_dereference_check(sta->hnext,
-                                           lockdep_is_held(&local->sta_lock) ||
                                            lockdep_is_held(&local->sta_mtx));
        }
        return sta;
@@ -204,16 +196,17 @@ struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata,
 }
 
 /**
- * __sta_info_free - internal STA free helper
+ * sta_info_free - free STA
  *
  * @local: pointer to the global information
  * @sta: STA info to free
  *
  * This function must undo everything done by sta_info_alloc()
- * that may happen before sta_info_insert().
+ * that may happen before sta_info_insert(). It may only be
+ * called when sta_info_insert() has not been attempted (and
+ * if that fails, the station is freed anyway.)
  */
-static void __sta_info_free(struct ieee80211_local *local,
-                           struct sta_info *sta)
+void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
 {
        if (sta->rate_ctrl) {
                rate_control_free_sta(sta);
@@ -227,10 +220,11 @@ static void __sta_info_free(struct ieee80211_local *local,
        kfree(sta);
 }
 
-/* Caller must hold local->sta_lock */
+/* Caller must hold local->sta_mtx */
 static void sta_info_hash_add(struct ieee80211_local *local,
                              struct sta_info *sta)
 {
+       lockdep_assert_held(&local->sta_mtx);
        sta->hnext = local->sta_hash[STA_HASH(sta->sta.addr)];
        RCU_INIT_POINTER(local->sta_hash[STA_HASH(sta->sta.addr)], sta);
 }
@@ -280,7 +274,7 @@ static int sta_prepare_rate_control(struct ieee80211_local *local,
 }
 
 struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
-                               u8 *addr, gfp_t gfp)
+                               const u8 *addr, gfp_t gfp)
 {
        struct ieee80211_local *local = sdata->local;
        struct sta_info *sta;
@@ -338,98 +332,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
        return sta;
 }
 
-static int sta_info_finish_insert(struct sta_info *sta,
-                               bool async, bool dummy_reinsert)
-{
-       struct ieee80211_local *local = sta->local;
-       struct ieee80211_sub_if_data *sdata = sta->sdata;
-       struct station_info sinfo;
-       unsigned long flags;
-       int err = 0;
-
-       lockdep_assert_held(&local->sta_mtx);
-
-       if (!sta->dummy || dummy_reinsert) {
-               /* notify driver */
-               err = drv_sta_add(local, sdata, &sta->sta);
-               if (err) {
-                       if (!async)
-                               return err;
-                       printk(KERN_DEBUG "%s: failed to add IBSS STA %pM to "
-                                         "driver (%d) - keeping it anyway.\n",
-                              sdata->name, sta->sta.addr, err);
-               } else {
-                       sta->uploaded = true;
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-                       if (async)
-                               wiphy_debug(local->hw.wiphy,
-                                           "Finished adding IBSS STA %pM\n",
-                                           sta->sta.addr);
-#endif
-               }
-
-               sdata = sta->sdata;
-       }
-
-       if (!dummy_reinsert) {
-               if (!async) {
-                       local->num_sta++;
-                       local->sta_generation++;
-                       smp_mb();
-
-                       /* make the station visible */
-                       spin_lock_irqsave(&local->sta_lock, flags);
-                       sta_info_hash_add(local, sta);
-                       spin_unlock_irqrestore(&local->sta_lock, flags);
-               }
-
-               list_add(&sta->list, &local->sta_list);
-       } else {
-               sta->dummy = false;
-       }
-
-       if (!sta->dummy) {
-               ieee80211_sta_debugfs_add(sta);
-               rate_control_add_sta_debugfs(sta);
-
-               memset(&sinfo, 0, sizeof(sinfo));
-               sinfo.filled = 0;
-               sinfo.generation = local->sta_generation;
-               cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL);
-       }
-
-       return 0;
-}
-
-static void sta_info_finish_pending(struct ieee80211_local *local)
-{
-       struct sta_info *sta;
-       unsigned long flags;
-
-       spin_lock_irqsave(&local->sta_lock, flags);
-       while (!list_empty(&local->sta_pending_list)) {
-               sta = list_first_entry(&local->sta_pending_list,
-                                      struct sta_info, list);
-               list_del(&sta->list);
-               spin_unlock_irqrestore(&local->sta_lock, flags);
-
-               sta_info_finish_insert(sta, true, false);
-
-               spin_lock_irqsave(&local->sta_lock, flags);
-       }
-       spin_unlock_irqrestore(&local->sta_lock, flags);
-}
-
-static void sta_info_finish_work(struct work_struct *work)
-{
-       struct ieee80211_local *local =
-               container_of(work, struct ieee80211_local, sta_finish_work);
-
-       mutex_lock(&local->sta_mtx);
-       sta_info_finish_pending(local);
-       mutex_unlock(&local->sta_mtx);
-}
-
 static int sta_info_insert_check(struct sta_info *sta)
 {
        struct ieee80211_sub_if_data *sdata = sta->sdata;
@@ -449,70 +351,24 @@ static int sta_info_insert_check(struct sta_info *sta)
        return 0;
 }
 
-static int sta_info_insert_ibss(struct sta_info *sta) __acquires(RCU)
-{
-       struct ieee80211_local *local = sta->local;
-       struct ieee80211_sub_if_data *sdata = sta->sdata;
-       unsigned long flags;
-
-       spin_lock_irqsave(&local->sta_lock, flags);
-       /* check if STA exists already */
-       if (sta_info_get_bss_rx(sdata, sta->sta.addr)) {
-               spin_unlock_irqrestore(&local->sta_lock, flags);
-               rcu_read_lock();
-               return -EEXIST;
-       }
-
-       local->num_sta++;
-       local->sta_generation++;
-       smp_mb();
-       sta_info_hash_add(local, sta);
-
-       list_add_tail(&sta->list, &local->sta_pending_list);
-
-       rcu_read_lock();
-       spin_unlock_irqrestore(&local->sta_lock, flags);
-
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-       wiphy_debug(local->hw.wiphy, "Added IBSS STA %pM\n",
-                       sta->sta.addr);
-#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
-
-       ieee80211_queue_work(&local->hw, &local->sta_finish_work);
-
-       return 0;
-}
-
 /*
  * should be called with sta_mtx locked
  * this function replaces the mutex lock
  * with a RCU lock
  */
-static int sta_info_insert_non_ibss(struct sta_info *sta) __acquires(RCU)
+static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
 {
        struct ieee80211_local *local = sta->local;
        struct ieee80211_sub_if_data *sdata = sta->sdata;
-       unsigned long flags;
        struct sta_info *exist_sta;
        bool dummy_reinsert = false;
        int err = 0;
 
        lockdep_assert_held(&local->sta_mtx);
 
-       /*
-        * On first glance, this will look racy, because the code
-        * in this function, which inserts a station with sleeping,
-        * unlocks the sta_lock between checking existence in the
-        * hash table and inserting into it.
-        *
-        * However, it is not racy against itself because it keeps
-        * the mutex locked.
-        */
-
-       spin_lock_irqsave(&local->sta_lock, flags);
        /*
         * check if STA exists already.
-        * only accept a scenario of a second call to sta_info_insert_non_ibss
+        * only accept a scenario of a second call to sta_info_insert_finish
         * with a dummy station entry that was inserted earlier
         * in that case - assume that the dummy station flag should
         * be removed.
@@ -522,20 +378,47 @@ static int sta_info_insert_non_ibss(struct sta_info *sta) __acquires(RCU)
                if (exist_sta == sta && sta->dummy) {
                        dummy_reinsert = true;
                } else {
-                       spin_unlock_irqrestore(&local->sta_lock, flags);
-                       mutex_unlock(&local->sta_mtx);
-                       rcu_read_lock();
-                       return -EEXIST;
+                       err = -EEXIST;
+                       goto out_err;
                }
        }
 
-       spin_unlock_irqrestore(&local->sta_lock, flags);
+       if (!sta->dummy || dummy_reinsert) {
+               /* notify driver */
+               err = drv_sta_add(local, sdata, &sta->sta);
+               if (err) {
+                       if (sdata->vif.type != NL80211_IFTYPE_ADHOC)
+                               goto out_err;
+                       printk(KERN_DEBUG "%s: failed to add IBSS STA %pM to "
+                                         "driver (%d) - keeping it anyway.\n",
+                              sdata->name, sta->sta.addr, err);
+               } else
+                       sta->uploaded = true;
+       }
 
-       err = sta_info_finish_insert(sta, false, dummy_reinsert);
-       if (err) {
-               mutex_unlock(&local->sta_mtx);
-               rcu_read_lock();
-               return err;
+       if (!dummy_reinsert) {
+               local->num_sta++;
+               local->sta_generation++;
+               smp_mb();
+
+               /* make the station visible */
+               sta_info_hash_add(local, sta);
+
+               list_add(&sta->list, &local->sta_list);
+       } else {
+               sta->dummy = false;
+       }
+
+       if (!sta->dummy) {
+               struct station_info sinfo;
+
+               ieee80211_sta_debugfs_add(sta);
+               rate_control_add_sta_debugfs(sta);
+
+               memset(&sinfo, 0, sizeof(sinfo));
+               sinfo.filled = 0;
+               sinfo.generation = local->sta_generation;
+               cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL);
        }
 
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
@@ -551,54 +434,35 @@ static int sta_info_insert_non_ibss(struct sta_info *sta) __acquires(RCU)
                mesh_accept_plinks_update(sdata);
 
        return 0;
+ out_err:
+       mutex_unlock(&local->sta_mtx);
+       rcu_read_lock();
+       return err;
 }
 
 int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU)
 {
        struct ieee80211_local *local = sta->local;
-       struct ieee80211_sub_if_data *sdata = sta->sdata;
        int err = 0;
 
+       might_sleep();
+
        err = sta_info_insert_check(sta);
        if (err) {
                rcu_read_lock();
                goto out_free;
        }
 
-       /*
-        * In ad-hoc mode, we sometimes need to insert stations
-        * from tasklet context from the RX path. To avoid races,
-        * always do so in that case -- see the comment below.
-        */
-       if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
-               err = sta_info_insert_ibss(sta);
-               if (err)
-                       goto out_free;
-
-               return 0;
-       }
-
-       /*
-        * It might seem that the function called below is in race against
-        * the function call above that atomically inserts the station... That,
-        * however, is not true because the above code can only
-        * be invoked for IBSS interfaces, and the below code will
-        * not be -- and the two do not race against each other as
-        * the hash table also keys off the interface.
-        */
-
-       might_sleep();
-
        mutex_lock(&local->sta_mtx);
 
-       err = sta_info_insert_non_ibss(sta);
+       err = sta_info_insert_finish(sta);
        if (err)
                goto out_free;
 
        return 0;
  out_free:
        BUG_ON(!err);
-       __sta_info_free(local, sta);
+       sta_info_free(local, sta);
        return err;
 }
 
@@ -625,7 +489,7 @@ int sta_info_reinsert(struct sta_info *sta)
 
        might_sleep();
 
-       err = sta_info_insert_non_ibss(sta);
+       err = sta_info_insert_finish(sta);
        rcu_read_unlock();
        return err;
 }
@@ -712,7 +576,7 @@ void sta_info_recalc_tim(struct sta_info *sta)
        }
 
  done:
-       spin_lock_irqsave(&local->sta_lock, flags);
+       spin_lock_irqsave(&local->tim_lock, flags);
 
        if (indicate_tim)
                __bss_tim_set(bss, sta->sta.aid);
@@ -725,7 +589,7 @@ void sta_info_recalc_tim(struct sta_info *sta)
                local->tim_in_locked_section = false;
        }
 
-       spin_unlock_irqrestore(&local->sta_lock, flags);
+       spin_unlock_irqrestore(&local->tim_lock, flags);
 }
 
 static bool sta_info_buffer_expired(struct sta_info *sta, struct sk_buff *skb)
@@ -849,8 +713,8 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
 {
        struct ieee80211_local *local;
        struct ieee80211_sub_if_data *sdata;
-       unsigned long flags;
        int ret, i, ac;
+       struct tid_ampdu_tx *tid_tx;
 
        might_sleep();
 
@@ -869,15 +733,12 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
        set_sta_flag(sta, WLAN_STA_BLOCK_BA);
        ieee80211_sta_tear_down_BA_sessions(sta, true);
 
-       spin_lock_irqsave(&local->sta_lock, flags);
        ret = sta_info_hash_del(local, sta);
-       /* this might still be the pending list ... which is fine */
-       if (!ret)
-               list_del(&sta->list);
-       spin_unlock_irqrestore(&local->sta_lock, flags);
        if (ret)
                return ret;
 
+       list_del(&sta->list);
+
        mutex_lock(&local->key_mtx);
        for (i = 0; i < NUM_DEFAULT_KEYS; i++)
                __ieee80211_key_free(key_mtx_dereference(local, sta->gtk[i]));
@@ -904,6 +765,9 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
        if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
                RCU_INIT_POINTER(sdata->u.vlan.sta, NULL);
 
+       while (sta->sta_state > IEEE80211_STA_NONE)
+               sta_info_move_state(sta, sta->sta_state - 1);
+
        if (sta->uploaded) {
                if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
                        sdata = container_of(sdata->bss,
@@ -949,7 +813,31 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
        }
 #endif
 
-       __sta_info_free(local, sta);
+       /* There could be some memory leaks because of ampdu tx pending queue
+        * not being freed before destroying the station info.
+        *
+        * Make sure that such queues are purged before freeing the station
+        * info.
+        * TODO: We have to somehow postpone the full destruction
+        * until the aggregation stop completes. Refer
+        * http://thread.gmane.org/gmane.linux.kernel.wireless.general/81936
+        */
+       for (i = 0; i < STA_TID_NUM; i++) {
+               if (!sta->ampdu_mlme.tid_tx[i])
+                       continue;
+               tid_tx = sta->ampdu_mlme.tid_tx[i];
+               if (skb_queue_len(&tid_tx->pending)) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
+                       wiphy_debug(local->hw.wiphy, "TX A-MPDU  purging %d "
+                               "packets for tid=%d\n",
+                               skb_queue_len(&tid_tx->pending), i);
+#endif /* CONFIG_MAC80211_HT_DEBUG */
+                       __skb_queue_purge(&tid_tx->pending);
+               }
+               kfree_rcu(tid_tx, rcu_head);
+       }
+
+       sta_info_free(local, sta);
 
        return 0;
 }
@@ -1005,11 +893,9 @@ static void sta_info_cleanup(unsigned long data)
 
 void sta_info_init(struct ieee80211_local *local)
 {
-       spin_lock_init(&local->sta_lock);
+       spin_lock_init(&local->tim_lock);
        mutex_init(&local->sta_mtx);
        INIT_LIST_HEAD(&local->sta_list);
-       INIT_LIST_HEAD(&local->sta_pending_list);
-       INIT_WORK(&local->sta_finish_work, sta_info_finish_work);
 
        setup_timer(&local->sta_cleanup, sta_info_cleanup,
                    (unsigned long)local);
@@ -1038,9 +924,6 @@ int sta_info_flush(struct ieee80211_local *local,
        might_sleep();
 
        mutex_lock(&local->sta_mtx);
-
-       sta_info_finish_pending(local);
-
        list_for_each_entry_safe(sta, tmp, &local->sta_list, list) {
                if (!sdata || sdata == sta->sdata)
                        WARN_ON(__sta_info_destroy(sta));
@@ -1513,3 +1396,56 @@ void ieee80211_sta_set_buffered(struct ieee80211_sta *pubsta,
        sta_info_recalc_tim(sta);
 }
 EXPORT_SYMBOL(ieee80211_sta_set_buffered);
+
+int sta_info_move_state_checked(struct sta_info *sta,
+                               enum ieee80211_sta_state new_state)
+{
+       might_sleep();
+
+       if (sta->sta_state == new_state)
+               return 0;
+
+       switch (new_state) {
+       case IEEE80211_STA_NONE:
+               if (sta->sta_state == IEEE80211_STA_AUTH)
+                       clear_bit(WLAN_STA_AUTH, &sta->_flags);
+               else
+                       return -EINVAL;
+               break;
+       case IEEE80211_STA_AUTH:
+               if (sta->sta_state == IEEE80211_STA_NONE)
+                       set_bit(WLAN_STA_AUTH, &sta->_flags);
+               else if (sta->sta_state == IEEE80211_STA_ASSOC)
+                       clear_bit(WLAN_STA_ASSOC, &sta->_flags);
+               else
+                       return -EINVAL;
+               break;
+       case IEEE80211_STA_ASSOC:
+               if (sta->sta_state == IEEE80211_STA_AUTH) {
+                       set_bit(WLAN_STA_ASSOC, &sta->_flags);
+               } else if (sta->sta_state == IEEE80211_STA_AUTHORIZED) {
+                       if (sta->sdata->vif.type == NL80211_IFTYPE_AP)
+                               atomic_dec(&sta->sdata->u.ap.num_sta_authorized);
+                       clear_bit(WLAN_STA_AUTHORIZED, &sta->_flags);
+               } else
+                       return -EINVAL;
+               break;
+       case IEEE80211_STA_AUTHORIZED:
+               if (sta->sta_state == IEEE80211_STA_ASSOC) {
+                       if (sta->sdata->vif.type == NL80211_IFTYPE_AP)
+                               atomic_inc(&sta->sdata->u.ap.num_sta_authorized);
+                       set_bit(WLAN_STA_AUTHORIZED, &sta->_flags);
+               } else
+                       return -EINVAL;
+               break;
+       default:
+               WARN(1, "invalid state %d", new_state);
+               return -EINVAL;
+       }
+
+       printk(KERN_DEBUG "%s: moving STA %pM to state %d\n",
+               sta->sdata->name, sta->sta.addr, new_state);
+       sta->sta_state = new_state;
+
+       return 0;
+}
index 1a14fab4bc9ae709365583ac548ee23f5106da14..15b3bb7d8629769b1e4756f58e29daeb160bca02 100644 (file)
@@ -73,6 +73,14 @@ enum ieee80211_sta_info_flags {
        WLAN_STA_4ADDR_EVENT,
 };
 
+enum ieee80211_sta_state {
+       /* NOTE: These need to be ordered correctly! */
+       IEEE80211_STA_NONE,
+       IEEE80211_STA_AUTH,
+       IEEE80211_STA_ASSOC,
+       IEEE80211_STA_AUTHORIZED,
+};
+
 #define STA_TID_NUM 16
 #define ADDBA_RESP_INTERVAL HZ
 #define HT_AGG_MAX_RETRIES             0x3
@@ -262,6 +270,7 @@ struct sta_ampdu_mlme {
  * @dummy: indicate a dummy station created for receiving
  *     EAP frames before association
  * @sta: station information we share with the driver
+ * @sta_state: duplicates information about station state (for debug)
  */
 struct sta_info {
        /* General information, mostly static */
@@ -283,6 +292,8 @@ struct sta_info {
 
        bool uploaded;
 
+       enum ieee80211_sta_state sta_state;
+
        /* use the accessors defined below */
        unsigned long _flags;
 
@@ -371,12 +382,18 @@ static inline enum nl80211_plink_state sta_plink_state(struct sta_info *sta)
 static inline void set_sta_flag(struct sta_info *sta,
                                enum ieee80211_sta_info_flags flag)
 {
+       WARN_ON(flag == WLAN_STA_AUTH ||
+               flag == WLAN_STA_ASSOC ||
+               flag == WLAN_STA_AUTHORIZED);
        set_bit(flag, &sta->_flags);
 }
 
 static inline void clear_sta_flag(struct sta_info *sta,
                                  enum ieee80211_sta_info_flags flag)
 {
+       WARN_ON(flag == WLAN_STA_AUTH ||
+               flag == WLAN_STA_ASSOC ||
+               flag == WLAN_STA_AUTHORIZED);
        clear_bit(flag, &sta->_flags);
 }
 
@@ -389,15 +406,32 @@ static inline int test_sta_flag(struct sta_info *sta,
 static inline int test_and_clear_sta_flag(struct sta_info *sta,
                                          enum ieee80211_sta_info_flags flag)
 {
+       WARN_ON(flag == WLAN_STA_AUTH ||
+               flag == WLAN_STA_ASSOC ||
+               flag == WLAN_STA_AUTHORIZED);
        return test_and_clear_bit(flag, &sta->_flags);
 }
 
 static inline int test_and_set_sta_flag(struct sta_info *sta,
                                        enum ieee80211_sta_info_flags flag)
 {
+       WARN_ON(flag == WLAN_STA_AUTH ||
+               flag == WLAN_STA_ASSOC ||
+               flag == WLAN_STA_AUTHORIZED);
        return test_and_set_bit(flag, &sta->_flags);
 }
 
+int sta_info_move_state_checked(struct sta_info *sta,
+                               enum ieee80211_sta_state new_state);
+
+static inline void sta_info_move_state(struct sta_info *sta,
+                                      enum ieee80211_sta_state new_state)
+{
+       int ret = sta_info_move_state_checked(sta, new_state);
+       WARN_ON_ONCE(ret);
+}
+
+
 void ieee80211_assign_tid_tx(struct sta_info *sta, int tid,
                             struct tid_ampdu_tx *tid_tx);
 
@@ -488,7 +522,10 @@ struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata,
  * until sta_info_insert().
  */
 struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
-                               u8 *addr, gfp_t gfp);
+                               const u8 *addr, gfp_t gfp);
+
+void sta_info_free(struct ieee80211_local *local, struct sta_info *sta);
+
 /*
  * Insert STA info into hash table/list, returns zero or a
  * -EEXIST if (if the same MAC address is already present).
index 46222ce0e5b12c7625a3271b3b996ac3b179c88b..30c265c98f73ccb190a0d642977f33d53298650f 100644 (file)
@@ -340,7 +340,6 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
        struct ieee80211_local *local = hw_to_local(hw);
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-       u16 frag, type;
        __le16 fc;
        struct ieee80211_supported_band *sband;
        struct ieee80211_sub_if_data *sdata;
@@ -476,12 +475,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
         * Fragments are passed to low-level drivers as separate skbs, so these
         * are actually fragments, not frames. Update frame counters only for
         * the first fragment of the frame. */
-
-       frag = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG;
-       type = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_FTYPE;
-
        if (info->flags & IEEE80211_TX_STAT_ACK) {
-               if (frag == 0) {
+               if (ieee80211_is_first_frag(hdr->seq_ctrl)) {
                        local->dot11TransmittedFrameCount++;
                        if (is_multicast_ether_addr(hdr->addr1))
                                local->dot11MulticastTransmittedFrameCount++;
@@ -496,11 +491,11 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
                 * with a multicast address in the address 1 field of type Data
                 * or Management. */
                if (!is_multicast_ether_addr(hdr->addr1) ||
-                   type == IEEE80211_FTYPE_DATA ||
-                   type == IEEE80211_FTYPE_MGMT)
+                   ieee80211_is_data(fc) ||
+                   ieee80211_is_mgmt(fc))
                        local->dot11TransmittedFragmentCount++;
        } else {
-               if (frag == 0)
+               if (ieee80211_is_first_frag(hdr->seq_ctrl))
                        local->dot11FailedCount++;
        }
 
@@ -572,7 +567,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
 
        /* Need to make a copy before skb->cb gets cleared */
        send_to_cooked = !!(info->flags & IEEE80211_TX_CTL_INJECTED) ||
-                       (type != IEEE80211_FTYPE_DATA);
+                        !(ieee80211_is_data(fc));
 
        /*
         * This is a bit racy but we can avoid a lot of work
index e74652d382453a2df34a99d9a7776f90e9f06dbf..edcd1c7ab83f94fcaffdb049a93540bdf77c5baf 100644 (file)
@@ -295,7 +295,6 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
 
        if (likely(tx->flags & IEEE80211_TX_UNICAST)) {
                if (unlikely(!assoc &&
-                            tx->sdata->vif.type != NL80211_IFTYPE_ADHOC &&
                             ieee80211_is_data(hdr->frame_control))) {
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
                        printk(KERN_DEBUG "%s: dropped data frame to not "
@@ -305,17 +304,14 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
                        I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc);
                        return TX_DROP;
                }
-       } else {
-               if (unlikely(ieee80211_is_data(hdr->frame_control) &&
-                            tx->local->num_sta == 0 &&
-                            tx->sdata->vif.type != NL80211_IFTYPE_ADHOC)) {
-                       /*
-                        * No associated STAs - no need to send multicast
-                        * frames.
-                        */
-                       return TX_DROP;
-               }
-               return TX_CONTINUE;
+       } else if (unlikely(tx->sdata->vif.type == NL80211_IFTYPE_AP &&
+                           ieee80211_is_data(hdr->frame_control) &&
+                           !atomic_read(&tx->sdata->u.ap.num_sta_authorized))) {
+               /*
+                * No associated STAs - no need to send multicast
+                * frames.
+                */
+               return TX_DROP;
        }
 
        return TX_CONTINUE;
@@ -2337,9 +2333,9 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
                        } else {
                                unsigned long flags;
 
-                               spin_lock_irqsave(&local->sta_lock, flags);
+                               spin_lock_irqsave(&local->tim_lock, flags);
                                ieee80211_beacon_add_tim(ap, skb, beacon);
-                               spin_unlock_irqrestore(&local->sta_lock, flags);
+                               spin_unlock_irqrestore(&local->tim_lock, flags);
                        }
 
                        if (tim_offset)
@@ -2700,15 +2696,15 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
 }
 EXPORT_SYMBOL(ieee80211_get_buffered_bc);
 
-void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
+void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata,
+                         struct sk_buff *skb, int tid)
 {
        skb_set_mac_header(skb, 0);
        skb_set_network_header(skb, 0);
        skb_set_transport_header(skb, 0);
 
-       /* Send all internal mgmt frames on VO. Accordingly set TID to 7. */
-       skb_set_queue_mapping(skb, IEEE80211_AC_VO);
-       skb->priority = 7;
+       skb_set_queue_mapping(skb, ieee802_1d_to_ac[tid]);
+       skb->priority = tid;
 
        /*
         * The other path calling ieee80211_xmit is from the tasklet,
index ac7ea2949de0ae870ccc445f872f50e140d58857..eb1a5f737a9cabd163d4bf9a039d0e39167cda5e 100644 (file)
@@ -1234,7 +1234,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 
                switch (sdata->vif.type) {
                case NL80211_IFTYPE_STATION:
-                       changed |= BSS_CHANGED_ASSOC;
+                       changed |= BSS_CHANGED_ASSOC |
+                                  BSS_CHANGED_ARP_FILTER;
                        mutex_lock(&sdata->u.mgd.mtx);
                        ieee80211_bss_info_change_notify(sdata, changed);
                        mutex_unlock(&sdata->u.mgd.mtx);
index 58cddadf8e8e2dfb5a915d621bebdc42b032609e..44c865b86d6f56f5324f63ad66b38c309cda8247 100644 (file)
@@ -14,5 +14,6 @@ menuconfig NFC
          be called nfc.
 
 source "net/nfc/nci/Kconfig"
+source "net/nfc/llcp/Kconfig"
 
 source "drivers/nfc/Kconfig"
index fbb550f2377b9298f755ee5a63428d9f93a06b69..7b4a6dcfa566b93a5f725daeceb5936797f2034c 100644 (file)
@@ -6,3 +6,4 @@ obj-$(CONFIG_NFC) += nfc.o
 obj-$(CONFIG_NFC_NCI) += nci/
 
 nfc-objs := core.o netlink.o af_nfc.o rawsock.o
+nfc-$(CONFIG_NFC_LLCP) += llcp/llcp.o llcp/commands.o llcp/sock.o
index 3ebc6b3aabacc3446fd5e425a78898f149e518d6..3ddf6e698df0569c2f8aafbb19cecd4fa15b9aa4 100644 (file)
  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__
 
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/nfc.h>
 
 #include "nfc.h"
 
@@ -180,6 +181,86 @@ error:
        return rc;
 }
 
+int nfc_dep_link_up(struct nfc_dev *dev, int target_index,
+                                       u8 comm_mode, u8 rf_mode)
+{
+       int rc = 0;
+
+       pr_debug("dev_name=%s comm:%d rf:%d\n",
+                       dev_name(&dev->dev), comm_mode, rf_mode);
+
+       if (!dev->ops->dep_link_up)
+               return -EOPNOTSUPP;
+
+       device_lock(&dev->dev);
+
+       if (!device_is_registered(&dev->dev)) {
+               rc = -ENODEV;
+               goto error;
+       }
+
+       if (dev->dep_link_up == true) {
+               rc = -EALREADY;
+               goto error;
+       }
+
+       rc = dev->ops->dep_link_up(dev, target_index, comm_mode, rf_mode);
+
+error:
+       device_unlock(&dev->dev);
+       return rc;
+}
+
+int nfc_dep_link_down(struct nfc_dev *dev)
+{
+       int rc = 0;
+
+       pr_debug("dev_name=%s\n", dev_name(&dev->dev));
+
+       if (!dev->ops->dep_link_down)
+               return -EOPNOTSUPP;
+
+       device_lock(&dev->dev);
+
+       if (!device_is_registered(&dev->dev)) {
+               rc = -ENODEV;
+               goto error;
+       }
+
+       if (dev->dep_link_up == false) {
+               rc = -EALREADY;
+               goto error;
+       }
+
+       if (dev->dep_rf_mode == NFC_RF_TARGET) {
+               rc = -EOPNOTSUPP;
+               goto error;
+       }
+
+       rc = dev->ops->dep_link_down(dev);
+       if (!rc) {
+               dev->dep_link_up = false;
+               nfc_llcp_mac_is_down(dev);
+               nfc_genl_dep_link_down_event(dev);
+       }
+
+error:
+       device_unlock(&dev->dev);
+       return rc;
+}
+
+int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx,
+                                       u8 comm_mode, u8 rf_mode)
+{
+       dev->dep_link_up = true;
+       dev->dep_rf_mode = rf_mode;
+
+       nfc_llcp_mac_is_up(dev, target_idx, comm_mode, rf_mode);
+
+       return nfc_genl_dep_link_up_event(dev, target_idx, comm_mode, rf_mode);
+}
+EXPORT_SYMBOL(nfc_dep_link_is_up);
+
 /**
  * nfc_activate_target - prepare the target for data exchange
  *
@@ -274,13 +355,54 @@ error:
        return rc;
 }
 
+int nfc_set_remote_general_bytes(struct nfc_dev *dev, u8 *gb, u8 gb_len)
+{
+       pr_debug("dev_name=%s gb_len=%d\n",
+                       dev_name(&dev->dev), gb_len);
+
+       if (gb_len > NFC_MAX_GT_LEN)
+               return -EINVAL;
+
+       return nfc_llcp_set_remote_gb(dev, gb, gb_len);
+}
+EXPORT_SYMBOL(nfc_set_remote_general_bytes);
+
+u8 *nfc_get_local_general_bytes(struct nfc_dev *dev, u8 *gt_len)
+{
+       return nfc_llcp_general_bytes(dev, gt_len);
+}
+EXPORT_SYMBOL(nfc_get_local_general_bytes);
+
 /**
- * nfc_alloc_skb - allocate a skb for data exchange responses
+ * nfc_alloc_send_skb - allocate a skb for data exchange responses
  *
  * @size: size to allocate
  * @gfp: gfp flags
  */
-struct sk_buff *nfc_alloc_skb(unsigned int size, gfp_t gfp)
+struct sk_buff *nfc_alloc_send_skb(struct nfc_dev *dev, struct sock *sk,
+                                       unsigned int flags, unsigned int size,
+                                       unsigned int *err)
+{
+       struct sk_buff *skb;
+       unsigned int total_size;
+
+       total_size = size +
+               dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE;
+
+       skb = sock_alloc_send_skb(sk, total_size, flags & MSG_DONTWAIT, err);
+       if (skb)
+               skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE);
+
+       return skb;
+}
+
+/**
+ * nfc_alloc_recv_skb - allocate a skb for data exchange responses
+ *
+ * @size: size to allocate
+ * @gfp: gfp flags
+ */
+struct sk_buff *nfc_alloc_recv_skb(unsigned int size, gfp_t gfp)
 {
        struct sk_buff *skb;
        unsigned int total_size;
@@ -293,7 +415,7 @@ struct sk_buff *nfc_alloc_skb(unsigned int size, gfp_t gfp)
 
        return skb;
 }
-EXPORT_SYMBOL(nfc_alloc_skb);
+EXPORT_SYMBOL(nfc_alloc_recv_skb);
 
 /**
  * nfc_targets_found - inform that targets were found
@@ -441,6 +563,10 @@ int nfc_register_device(struct nfc_dev *dev)
        if (rc < 0)
                return rc;
 
+       rc = nfc_llcp_register_device(dev);
+       if (rc)
+               pr_err("Could not register llcp device\n");
+
        rc = nfc_genl_device_added(dev);
        if (rc)
                pr_debug("The userspace won't be notified that the device %s was added\n",
@@ -472,6 +598,8 @@ void nfc_unregister_device(struct nfc_dev *dev)
 
        mutex_unlock(&nfc_devlist_mutex);
 
+       nfc_llcp_unregister_device(dev);
+
        rc = nfc_genl_device_removed(dev);
        if (rc)
                pr_debug("The userspace won't be notified that the device %s was removed\n",
@@ -501,6 +629,10 @@ static int __init nfc_init(void)
        if (rc)
                goto err_rawsock;
 
+       rc = nfc_llcp_init();
+       if (rc)
+               goto err_llcp_sock;
+
        rc = af_nfc_init();
        if (rc)
                goto err_af_nfc;
@@ -508,6 +640,8 @@ static int __init nfc_init(void)
        return 0;
 
 err_af_nfc:
+       nfc_llcp_exit();
+err_llcp_sock:
        rawsock_exit();
 err_rawsock:
        nfc_genl_exit();
@@ -519,6 +653,7 @@ err_genl:
 static void __exit nfc_exit(void)
 {
        af_nfc_exit();
+       nfc_llcp_exit();
        rawsock_exit();
        nfc_genl_exit();
        class_unregister(&nfc_class);
diff --git a/net/nfc/llcp/Kconfig b/net/nfc/llcp/Kconfig
new file mode 100644 (file)
index 0000000..fbf5e81
--- /dev/null
@@ -0,0 +1,7 @@
+config NFC_LLCP
+       depends on NFC && EXPERIMENTAL
+       bool "NFC LLCP support (EXPERIMENTAL)"
+       default n
+       help
+        Say Y here if you want to build support for a kernel NFC LLCP
+        implementation.
\ No newline at end of file
diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c
new file mode 100644 (file)
index 0000000..151f2ef
--- /dev/null
@@ -0,0 +1,399 @@
+/*
+ * Copyright (C) 2011  Intel Corporation. All rights reserved.
+ *
+ * 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; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define pr_fmt(fmt) "llcp: %s: " fmt, __func__
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/nfc.h>
+
+#include <net/nfc/nfc.h>
+
+#include "../nfc.h"
+#include "llcp.h"
+
+static u8 llcp_tlv_length[LLCP_TLV_MAX] = {
+       0,
+       1, /* VERSION */
+       2, /* MIUX */
+       2, /* WKS */
+       1, /* LTO */
+       1, /* RW */
+       0, /* SN */
+       1, /* OPT */
+       0, /* SDREQ */
+       2, /* SDRES */
+
+};
+
+static u8 llcp_tlv8(u8 *tlv, u8 type)
+{
+       if (tlv[0] != type || tlv[1] != llcp_tlv_length[tlv[0]])
+               return 0;
+
+       return tlv[2];
+}
+
+static u8 llcp_tlv16(u8 *tlv, u8 type)
+{
+       if (tlv[0] != type || tlv[1] != llcp_tlv_length[tlv[0]])
+               return 0;
+
+       return be16_to_cpu(*((__be16 *)(tlv + 2)));
+}
+
+
+static u8 llcp_tlv_version(u8 *tlv)
+{
+       return llcp_tlv8(tlv, LLCP_TLV_VERSION);
+}
+
+static u16 llcp_tlv_miux(u8 *tlv)
+{
+       return llcp_tlv16(tlv, LLCP_TLV_MIUX) & 0x7f;
+}
+
+static u16 llcp_tlv_wks(u8 *tlv)
+{
+       return llcp_tlv16(tlv, LLCP_TLV_WKS);
+}
+
+static u16 llcp_tlv_lto(u8 *tlv)
+{
+       return llcp_tlv8(tlv, LLCP_TLV_LTO);
+}
+
+static u8 llcp_tlv_opt(u8 *tlv)
+{
+       return llcp_tlv8(tlv, LLCP_TLV_OPT);
+}
+
+static u8 llcp_tlv_rw(u8 *tlv)
+{
+       return llcp_tlv8(tlv, LLCP_TLV_RW) & 0xf;
+}
+
+u8 *nfc_llcp_build_tlv(u8 type, u8 *value, u8 value_length, u8 *tlv_length)
+{
+       u8 *tlv, length;
+
+       pr_debug("type %d\n", type);
+
+       if (type >= LLCP_TLV_MAX)
+               return NULL;
+
+       length = llcp_tlv_length[type];
+       if (length == 0 && value_length == 0)
+               return NULL;
+       else
+               length = value_length;
+
+       *tlv_length = 2 + length;
+       tlv = kzalloc(2 + length, GFP_KERNEL);
+       if (tlv == NULL)
+               return tlv;
+
+       tlv[0] = type;
+       tlv[1] = length;
+       memcpy(tlv + 2, value, length);
+
+       return tlv;
+}
+
+int nfc_llcp_parse_tlv(struct nfc_llcp_local *local,
+                       u8 *tlv_array, u16 tlv_array_len)
+{
+       u8 *tlv = tlv_array, type, length, offset = 0;
+
+       pr_debug("TLV array length %d\n", tlv_array_len);
+
+       if (local == NULL)
+               return -ENODEV;
+
+       while (offset < tlv_array_len) {
+               type = tlv[0];
+               length = tlv[1];
+
+               pr_debug("type 0x%x length %d\n", type, length);
+
+               switch (type) {
+               case LLCP_TLV_VERSION:
+                       local->remote_version = llcp_tlv_version(tlv);
+                       break;
+               case LLCP_TLV_MIUX:
+                       local->remote_miu = llcp_tlv_miux(tlv) + 128;
+                       break;
+               case LLCP_TLV_WKS:
+                       local->remote_wks = llcp_tlv_wks(tlv);
+                       break;
+               case LLCP_TLV_LTO:
+                       local->remote_lto = llcp_tlv_lto(tlv) * 10;
+                       break;
+               case LLCP_TLV_OPT:
+                       local->remote_opt = llcp_tlv_opt(tlv);
+                       break;
+               case LLCP_TLV_RW:
+                       local->remote_rw = llcp_tlv_rw(tlv);
+                       break;
+               default:
+                       pr_err("Invalid gt tlv value 0x%x\n", type);
+                       break;
+               }
+
+               offset += length + 2;
+               tlv += length + 2;
+       }
+
+       pr_debug("version 0x%x miu %d lto %d opt 0x%x wks 0x%x rw %d\n",
+               local->remote_version, local->remote_miu,
+               local->remote_lto, local->remote_opt,
+               local->remote_wks, local->remote_rw);
+
+       return 0;
+}
+
+static struct sk_buff *llcp_add_header(struct sk_buff *pdu,
+                                       u8 dsap, u8 ssap, u8 ptype)
+{
+       u8 header[2];
+
+       pr_debug("ptype 0x%x dsap 0x%x ssap 0x%x\n", ptype, dsap, ssap);
+
+       header[0] = (u8)((dsap << 2) | (ptype >> 2));
+       header[1] = (u8)((ptype << 6) | ssap);
+
+       pr_debug("header 0x%x 0x%x\n", header[0], header[1]);
+
+       memcpy(skb_put(pdu, LLCP_HEADER_SIZE), header, LLCP_HEADER_SIZE);
+
+       return pdu;
+}
+
+static struct sk_buff *llcp_add_tlv(struct sk_buff *pdu, u8 *tlv, u8 tlv_length)
+{
+       /* XXX Add an skb length check */
+
+       if (tlv == NULL)
+               return NULL;
+
+       memcpy(skb_put(pdu, tlv_length), tlv, tlv_length);
+
+       return pdu;
+}
+
+static struct sk_buff *llcp_allocate_pdu(struct nfc_llcp_sock *sock,
+                                                       u8 cmd, u16 size)
+{
+       struct sk_buff *skb;
+       int err;
+
+       if (sock->ssap == 0)
+               return NULL;
+
+       skb = nfc_alloc_send_skb(sock->dev, &sock->sk, MSG_DONTWAIT,
+                                       size + LLCP_HEADER_SIZE, &err);
+       if (skb == NULL) {
+               pr_err("Could not allocate PDU\n");
+               return NULL;
+       }
+
+       skb = llcp_add_header(skb, sock->dsap, sock->ssap, cmd);
+
+       return skb;
+}
+
+int nfc_llcp_disconnect(struct nfc_llcp_sock *sock)
+{
+       struct sk_buff *skb;
+       struct nfc_dev *dev;
+       struct nfc_llcp_local *local;
+       u16 size = 0;
+
+       pr_debug("Sending DISC\n");
+
+       local = sock->local;
+       if (local == NULL)
+               return -ENODEV;
+
+       dev = sock->dev;
+       if (dev == NULL)
+               return -ENODEV;
+
+       size += LLCP_HEADER_SIZE;
+       size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE;
+
+       skb = alloc_skb(size, GFP_ATOMIC);
+       if (skb == NULL)
+               return -ENOMEM;
+
+       skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE);
+
+       skb = llcp_add_header(skb, sock->ssap, sock->dsap, LLCP_PDU_DISC);
+
+       skb_queue_tail(&local->tx_queue, skb);
+
+       return 0;
+}
+
+int nfc_llcp_send_symm(struct nfc_dev *dev)
+{
+       struct sk_buff *skb;
+       struct nfc_llcp_local *local;
+       u16 size = 0;
+
+       pr_debug("Sending SYMM\n");
+
+       local = nfc_llcp_find_local(dev);
+       if (local == NULL)
+               return -ENODEV;
+
+       size += LLCP_HEADER_SIZE;
+       size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE;
+
+       skb = alloc_skb(size, GFP_KERNEL);
+       if (skb == NULL)
+               return -ENOMEM;
+
+       skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE);
+
+       skb = llcp_add_header(skb, 0, 0, LLCP_PDU_SYMM);
+
+       return nfc_data_exchange(dev, local->target_idx, skb,
+                                       nfc_llcp_recv, local);
+}
+
+int nfc_llcp_send_connect(struct nfc_llcp_sock *sock)
+{
+       struct nfc_llcp_local *local;
+       struct sk_buff *skb;
+       u8 *service_name_tlv = NULL, service_name_tlv_length;
+       int err;
+       u16 size = 0;
+
+       pr_debug("Sending CONNECT\n");
+
+       local = sock->local;
+       if (local == NULL)
+               return -ENODEV;
+
+       if (sock->service_name != NULL) {
+               service_name_tlv = nfc_llcp_build_tlv(LLCP_TLV_SN,
+                                       sock->service_name,
+                                       sock->service_name_len,
+                                       &service_name_tlv_length);
+               size += service_name_tlv_length;
+       }
+
+       pr_debug("SKB size %d SN length %zu\n", size, sock->service_name_len);
+
+       skb = llcp_allocate_pdu(sock, LLCP_PDU_CONNECT, size);
+       if (skb == NULL) {
+               err = -ENOMEM;
+               goto error_tlv;
+       }
+
+       if (service_name_tlv != NULL)
+               skb = llcp_add_tlv(skb, service_name_tlv,
+                                       service_name_tlv_length);
+
+       skb_queue_tail(&local->tx_queue, skb);
+
+       return 0;
+
+error_tlv:
+       pr_err("error %d\n", err);
+
+       kfree(service_name_tlv);
+
+       return err;
+}
+
+int nfc_llcp_send_cc(struct nfc_llcp_sock *sock)
+{
+       struct nfc_llcp_local *local;
+       struct sk_buff *skb;
+
+       pr_debug("Sending CC\n");
+
+       local = sock->local;
+       if (local == NULL)
+               return -ENODEV;
+
+       skb = llcp_allocate_pdu(sock, LLCP_PDU_CC, 0);
+       if (skb == NULL)
+               return -ENOMEM;
+
+       skb_queue_tail(&local->tx_queue, skb);
+
+       return 0;
+}
+
+int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason)
+{
+       struct sk_buff *skb;
+       struct nfc_dev *dev;
+       u16 size = 1; /* Reason code */
+
+       pr_debug("Sending DM reason 0x%x\n", reason);
+
+       if (local == NULL)
+               return -ENODEV;
+
+       dev = local->dev;
+       if (dev == NULL)
+               return -ENODEV;
+
+       size += LLCP_HEADER_SIZE;
+       size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE;
+
+       skb = alloc_skb(size, GFP_KERNEL);
+       if (skb == NULL)
+               return -ENOMEM;
+
+       skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE);
+
+       skb = llcp_add_header(skb, ssap, dsap, LLCP_PDU_DM);
+
+       memcpy(skb_put(skb, 1), &reason, 1);
+
+       skb_queue_head(&local->tx_queue, skb);
+
+       return 0;
+}
+
+int nfc_llcp_send_disconnect(struct nfc_llcp_sock *sock)
+{
+       struct sk_buff *skb;
+       struct nfc_llcp_local *local;
+
+       pr_debug("Send DISC\n");
+
+       local = sock->local;
+       if (local == NULL)
+               return -ENODEV;
+
+       skb = llcp_allocate_pdu(sock, LLCP_PDU_DISC, 0);
+       if (skb == NULL)
+               return -ENOMEM;
+
+       skb_queue_head(&local->tx_queue, skb);
+
+       return 0;
+}
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c
new file mode 100644 (file)
index 0000000..67756b2
--- /dev/null
@@ -0,0 +1,973 @@
+/*
+ * Copyright (C) 2011  Intel Corporation. All rights reserved.
+ *
+ * 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; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define pr_fmt(fmt) "llcp: %s: " fmt, __func__
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/nfc.h>
+
+#include "../nfc.h"
+#include "llcp.h"
+
+static u8 llcp_magic[3] = {0x46, 0x66, 0x6d};
+
+static struct list_head llcp_devices;
+
+static void nfc_llcp_socket_release(struct nfc_llcp_local *local)
+{
+       struct nfc_llcp_sock *parent, *s, *n;
+       struct sock *sk, *parent_sk;
+       int i;
+
+
+       mutex_lock(&local->socket_lock);
+
+       for (i = 0; i < LLCP_MAX_SAP; i++) {
+               parent = local->sockets[i];
+               if (parent == NULL)
+                       continue;
+
+               /* Release all child sockets */
+               list_for_each_entry_safe(s, n, &parent->list, list) {
+                       list_del(&s->list);
+                       sk = &s->sk;
+
+                       lock_sock(sk);
+
+                       if (sk->sk_state == LLCP_CONNECTED)
+                               nfc_put_device(s->dev);
+
+                       sk->sk_state = LLCP_CLOSED;
+                       sock_set_flag(sk, SOCK_DEAD);
+
+                       release_sock(sk);
+               }
+
+               parent_sk = &parent->sk;
+
+               lock_sock(parent_sk);
+
+               if (parent_sk->sk_state == LLCP_LISTEN) {
+                       struct nfc_llcp_sock *lsk, *n;
+                       struct sock *accept_sk;
+
+                       list_for_each_entry_safe(lsk, n, &parent->accept_queue,
+                                                               accept_queue) {
+                               accept_sk = &lsk->sk;
+                               lock_sock(accept_sk);
+
+                               nfc_llcp_accept_unlink(accept_sk);
+
+                               accept_sk->sk_state = LLCP_CLOSED;
+                               sock_set_flag(accept_sk, SOCK_DEAD);
+
+                               release_sock(accept_sk);
+
+                               sock_orphan(accept_sk);
+                       }
+               }
+
+               if (parent_sk->sk_state == LLCP_CONNECTED)
+                       nfc_put_device(parent->dev);
+
+               parent_sk->sk_state = LLCP_CLOSED;
+               sock_set_flag(parent_sk, SOCK_DEAD);
+
+               release_sock(parent_sk);
+       }
+
+       mutex_unlock(&local->socket_lock);
+}
+
+static void nfc_llcp_timeout_work(struct work_struct *work)
+{
+       struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local,
+                                                       timeout_work);
+
+       nfc_dep_link_down(local->dev);
+}
+
+static void nfc_llcp_symm_timer(unsigned long data)
+{
+       struct nfc_llcp_local *local = (struct nfc_llcp_local *) data;
+
+       pr_err("SYMM timeout\n");
+
+       queue_work(local->timeout_wq, &local->timeout_work);
+}
+
+struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev)
+{
+       struct nfc_llcp_local *local, *n;
+
+       list_for_each_entry_safe(local, n, &llcp_devices, list)
+               if (local->dev == dev)
+                       return local;
+
+       pr_debug("No device found\n");
+
+       return NULL;
+}
+
+static char *wks[] = {
+       NULL,
+       NULL, /* SDP */
+       "urn:nfc:sn:ip",
+       "urn:nfc:sn:obex",
+       "urn:nfc:sn:snep",
+};
+
+static int nfc_llcp_wks_sap(char *service_name, size_t service_name_len)
+{
+       int sap, num_wks;
+
+       pr_debug("%s\n", service_name);
+
+       if (service_name == NULL)
+               return -EINVAL;
+
+       num_wks = ARRAY_SIZE(wks);
+
+       for (sap = 0 ; sap < num_wks; sap++) {
+               if (wks[sap] == NULL)
+                       continue;
+
+               if (strncmp(wks[sap], service_name, service_name_len) == 0)
+                       return sap;
+       }
+
+       return -EINVAL;
+}
+
+u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local,
+                               struct nfc_llcp_sock *sock)
+{
+       mutex_lock(&local->sdp_lock);
+
+       if (sock->service_name != NULL && sock->service_name_len > 0) {
+               int ssap = nfc_llcp_wks_sap(sock->service_name,
+                                               sock->service_name_len);
+
+               if (ssap > 0) {
+                       pr_debug("WKS %d\n", ssap);
+
+                       /* This is a WKS, let's check if it's free */
+                       if (local->local_wks & BIT(ssap)) {
+                               mutex_unlock(&local->sdp_lock);
+
+                               return LLCP_SAP_MAX;
+                       }
+
+                       set_bit(BIT(ssap), &local->local_wks);
+                       mutex_unlock(&local->sdp_lock);
+
+                       return ssap;
+               }
+
+               /*
+                * This is not a well known service,
+                * we should try to find a local SDP free spot
+                */
+               ssap = find_first_zero_bit(&local->local_sdp, LLCP_SDP_NUM_SAP);
+               if (ssap == LLCP_SDP_NUM_SAP) {
+                       mutex_unlock(&local->sdp_lock);
+
+                       return LLCP_SAP_MAX;
+               }
+
+               pr_debug("SDP ssap %d\n", LLCP_WKS_NUM_SAP + ssap);
+
+               set_bit(BIT(ssap), &local->local_sdp);
+               mutex_unlock(&local->sdp_lock);
+
+               return LLCP_WKS_NUM_SAP + ssap;
+
+       } else if (sock->ssap != 0) {
+               if (sock->ssap < LLCP_WKS_NUM_SAP) {
+                       if (!(local->local_wks & BIT(sock->ssap))) {
+                               set_bit(BIT(sock->ssap), &local->local_wks);
+                               mutex_unlock(&local->sdp_lock);
+
+                               return sock->ssap;
+                       }
+
+               } else if (sock->ssap < LLCP_SDP_NUM_SAP) {
+                       if (!(local->local_sdp &
+                               BIT(sock->ssap - LLCP_WKS_NUM_SAP))) {
+                               set_bit(BIT(sock->ssap - LLCP_WKS_NUM_SAP),
+                                                       &local->local_sdp);
+                               mutex_unlock(&local->sdp_lock);
+
+                               return sock->ssap;
+                       }
+               }
+       }
+
+       mutex_unlock(&local->sdp_lock);
+
+       return LLCP_SAP_MAX;
+}
+
+u8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local)
+{
+       u8 local_ssap;
+
+       mutex_lock(&local->sdp_lock);
+
+       local_ssap = find_first_zero_bit(&local->local_sap, LLCP_LOCAL_NUM_SAP);
+       if (local_ssap == LLCP_LOCAL_NUM_SAP) {
+               mutex_unlock(&local->sdp_lock);
+               return LLCP_SAP_MAX;
+       }
+
+       set_bit(BIT(local_ssap), &local->local_sap);
+
+       mutex_unlock(&local->sdp_lock);
+
+       return local_ssap + LLCP_LOCAL_SAP_OFFSET;
+}
+
+void nfc_llcp_put_ssap(struct nfc_llcp_local *local, u8 ssap)
+{
+       u8 local_ssap;
+       unsigned long *sdp;
+
+       if (ssap < LLCP_WKS_NUM_SAP) {
+               local_ssap = ssap;
+               sdp = &local->local_wks;
+       } else if (ssap < LLCP_LOCAL_NUM_SAP) {
+               local_ssap = ssap - LLCP_WKS_NUM_SAP;
+               sdp = &local->local_sdp;
+       } else if (ssap < LLCP_MAX_SAP) {
+               local_ssap = ssap - LLCP_LOCAL_NUM_SAP;
+               sdp = &local->local_sap;
+       } else {
+               return;
+       }
+
+       mutex_lock(&local->sdp_lock);
+
+       clear_bit(1 << local_ssap, sdp);
+
+       mutex_unlock(&local->sdp_lock);
+}
+
+u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, u8 *general_bytes_len)
+{
+       struct nfc_llcp_local *local;
+
+       local = nfc_llcp_find_local(dev);
+       if (local == NULL) {
+               *general_bytes_len = 0;
+               return NULL;
+       }
+
+       *general_bytes_len = local->gb_len;
+
+       return local->gb;
+}
+
+static int nfc_llcp_build_gb(struct nfc_llcp_local *local)
+{
+       u8 *gb_cur, *version_tlv, version, version_length;
+       u8 *lto_tlv, lto, lto_length;
+       u8 *wks_tlv, wks_length;
+       u8 gb_len = 0;
+
+       version = LLCP_VERSION_11;
+       version_tlv = nfc_llcp_build_tlv(LLCP_TLV_VERSION, &version,
+                                                       1, &version_length);
+       gb_len += version_length;
+
+       /* 1500 ms */
+       lto = 150;
+       lto_tlv = nfc_llcp_build_tlv(LLCP_TLV_VERSION, &lto, 1, &lto_length);
+       gb_len += lto_length;
+
+       pr_debug("Local wks 0x%lx\n", local->local_wks);
+       wks_tlv = nfc_llcp_build_tlv(LLCP_TLV_WKS, (u8 *)&local->local_wks, 2,
+                                                               &wks_length);
+       gb_len += wks_length;
+
+       gb_len += ARRAY_SIZE(llcp_magic);
+
+       if (gb_len > NFC_MAX_GT_LEN) {
+               kfree(version_tlv);
+               return -EINVAL;
+       }
+
+       gb_cur = local->gb;
+
+       memcpy(gb_cur, llcp_magic, ARRAY_SIZE(llcp_magic));
+       gb_cur += ARRAY_SIZE(llcp_magic);
+
+       memcpy(gb_cur, version_tlv, version_length);
+       gb_cur += version_length;
+
+       memcpy(gb_cur, lto_tlv, lto_length);
+       gb_cur += lto_length;
+
+       memcpy(gb_cur, wks_tlv, wks_length);
+       gb_cur += wks_length;
+
+       kfree(version_tlv);
+       kfree(lto_tlv);
+
+       local->gb_len = gb_len;
+
+       return 0;
+}
+
+int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len)
+{
+       struct nfc_llcp_local *local = nfc_llcp_find_local(dev);
+
+       if (local == NULL) {
+               pr_err("No LLCP device\n");
+               return -ENODEV;
+       }
+
+       memset(local->remote_gb, 0, NFC_MAX_GT_LEN);
+       memcpy(local->remote_gb, gb, gb_len);
+       local->remote_gb_len = gb_len;
+
+       if (local->remote_gb == NULL ||
+                       local->remote_gb_len == 0)
+               return -ENODEV;
+
+       if (memcmp(local->remote_gb, llcp_magic, 3)) {
+               pr_err("MAC does not support LLCP\n");
+               return -EINVAL;
+       }
+
+       return nfc_llcp_parse_tlv(local,
+                       &local->remote_gb[3], local->remote_gb_len - 3);
+}
+
+static void nfc_llcp_tx_work(struct work_struct *work)
+{
+       struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local,
+                                                       tx_work);
+       struct sk_buff *skb;
+
+       skb = skb_dequeue(&local->tx_queue);
+       if (skb != NULL) {
+               pr_debug("Sending pending skb\n");
+               nfc_data_exchange(local->dev, local->target_idx,
+                                       skb, nfc_llcp_recv, local);
+       } else {
+               nfc_llcp_send_symm(local->dev);
+       }
+
+       mod_timer(&local->link_timer,
+                       jiffies + msecs_to_jiffies(local->remote_lto));
+}
+
+static u8 nfc_llcp_dsap(struct sk_buff *pdu)
+{
+       return (pdu->data[0] & 0xfc) >> 2;
+}
+
+static u8 nfc_llcp_ptype(struct sk_buff *pdu)
+{
+       return ((pdu->data[0] & 0x03) << 2) | ((pdu->data[1] & 0xc0) >> 6);
+}
+
+static u8 nfc_llcp_ssap(struct sk_buff *pdu)
+{
+       return pdu->data[1] & 0x3f;
+}
+
+static u8 nfc_llcp_ns(struct sk_buff *pdu)
+{
+       return pdu->data[2] >> 4;
+}
+
+static u8 nfc_llcp_nr(struct sk_buff *pdu)
+{
+       return pdu->data[2] & 0xf;
+}
+
+static void nfc_llcp_set_nrns(struct nfc_llcp_sock *sock, struct sk_buff *pdu)
+{
+       pdu->data[2] = (sock->send_n << 4) | ((sock->recv_n - 1) % 16);
+       sock->send_n = (sock->send_n + 1) % 16;
+       sock->recv_ack_n = (sock->recv_n - 1) % 16;
+}
+
+static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local,
+                                               u8 ssap, u8 dsap)
+{
+       struct nfc_llcp_sock *sock, *llcp_sock, *n;
+
+       if (ssap == 0 && dsap == 0)
+               return NULL;
+
+       mutex_lock(&local->socket_lock);
+       sock = local->sockets[ssap];
+       if (sock == NULL) {
+               mutex_unlock(&local->socket_lock);
+               return NULL;
+       }
+
+       pr_debug("root dsap %d (%d)\n", sock->dsap, dsap);
+
+       if (sock->dsap == dsap) {
+               sock_hold(&sock->sk);
+               mutex_unlock(&local->socket_lock);
+               return sock;
+       }
+
+       list_for_each_entry_safe(llcp_sock, n, &sock->list, list) {
+               pr_debug("llcp_sock %p sk %p dsap %d\n", llcp_sock,
+                               &llcp_sock->sk, llcp_sock->dsap);
+               if (llcp_sock->dsap == dsap) {
+                       sock_hold(&llcp_sock->sk);
+                       mutex_unlock(&local->socket_lock);
+                       return llcp_sock;
+               }
+       }
+
+       pr_err("Could not find socket for %d %d\n", ssap, dsap);
+
+       mutex_unlock(&local->socket_lock);
+
+       return NULL;
+}
+
+static void nfc_llcp_sock_put(struct nfc_llcp_sock *sock)
+{
+       sock_put(&sock->sk);
+}
+
+static u8 *nfc_llcp_connect_sn(struct sk_buff *skb, size_t *sn_len)
+{
+       u8 *tlv = &skb->data[2], type, length;
+       size_t tlv_array_len = skb->len - LLCP_HEADER_SIZE, offset = 0;
+
+       while (offset < tlv_array_len) {
+               type = tlv[0];
+               length = tlv[1];
+
+               pr_debug("type 0x%x length %d\n", type, length);
+
+               if (type == LLCP_TLV_SN) {
+                       *sn_len = length;
+                       return &tlv[2];
+               }
+
+               offset += length + 2;
+               tlv += length + 2;
+       }
+
+       return NULL;
+}
+
+static void nfc_llcp_recv_connect(struct nfc_llcp_local *local,
+                               struct sk_buff *skb)
+{
+       struct sock *new_sk, *parent;
+       struct nfc_llcp_sock *sock, *new_sock;
+       u8 dsap, ssap, bound_sap, reason;
+
+       dsap = nfc_llcp_dsap(skb);
+       ssap = nfc_llcp_ssap(skb);
+
+       pr_debug("%d %d\n", dsap, ssap);
+
+       nfc_llcp_parse_tlv(local, &skb->data[LLCP_HEADER_SIZE],
+                               skb->len - LLCP_HEADER_SIZE);
+
+       if (dsap != LLCP_SAP_SDP) {
+               bound_sap = dsap;
+
+               mutex_lock(&local->socket_lock);
+               sock = local->sockets[dsap];
+               if (sock == NULL) {
+                       mutex_unlock(&local->socket_lock);
+                       reason = LLCP_DM_NOBOUND;
+                       goto fail;
+               }
+
+               sock_hold(&sock->sk);
+               mutex_unlock(&local->socket_lock);
+
+               lock_sock(&sock->sk);
+
+               if (sock->dsap == LLCP_SAP_SDP &&
+                               sock->sk.sk_state == LLCP_LISTEN)
+                       goto enqueue;
+       } else {
+               u8 *sn;
+               size_t sn_len;
+
+               sn = nfc_llcp_connect_sn(skb, &sn_len);
+               if (sn == NULL) {
+                       reason = LLCP_DM_NOBOUND;
+                       goto fail;
+               }
+
+               pr_debug("Service name length %zu\n", sn_len);
+
+               mutex_lock(&local->socket_lock);
+               for (bound_sap = 0; bound_sap < LLCP_LOCAL_SAP_OFFSET;
+                                                               bound_sap++) {
+                       sock = local->sockets[bound_sap];
+                       if (sock == NULL)
+                               continue;
+
+                       if (sock->service_name == NULL ||
+                               sock->service_name_len == 0)
+                                       continue;
+
+                       if (sock->service_name_len != sn_len)
+                               continue;
+
+                       if (sock->dsap == LLCP_SAP_SDP &&
+                                       sock->sk.sk_state == LLCP_LISTEN &&
+                                       !memcmp(sn, sock->service_name, sn_len)) {
+                               pr_debug("Found service name at SAP %d\n",
+                                                               bound_sap);
+                               sock_hold(&sock->sk);
+                               mutex_unlock(&local->socket_lock);
+
+                               lock_sock(&sock->sk);
+
+                               goto enqueue;
+                       }
+               }
+
+       }
+
+       mutex_unlock(&local->socket_lock);
+
+       reason = LLCP_DM_NOBOUND;
+       goto fail;
+
+enqueue:
+       parent = &sock->sk;
+
+       if (sk_acceptq_is_full(parent)) {
+               reason = LLCP_DM_REJ;
+               release_sock(&sock->sk);
+               sock_put(&sock->sk);
+               goto fail;
+       }
+
+       new_sk = nfc_llcp_sock_alloc(NULL, parent->sk_type,
+                                    GFP_ATOMIC);
+       if (new_sk == NULL) {
+               reason = LLCP_DM_REJ;
+               release_sock(&sock->sk);
+               sock_put(&sock->sk);
+               goto fail;
+       }
+
+       new_sock = nfc_llcp_sock(new_sk);
+       new_sock->dev = local->dev;
+       new_sock->local = local;
+       new_sock->nfc_protocol = sock->nfc_protocol;
+       new_sock->ssap = bound_sap;
+       new_sock->dsap = ssap;
+       new_sock->parent = parent;
+
+       pr_debug("new sock %p sk %p\n", new_sock, &new_sock->sk);
+
+       list_add_tail(&new_sock->list, &sock->list);
+
+       nfc_llcp_accept_enqueue(&sock->sk, new_sk);
+
+       nfc_get_device(local->dev->idx);
+
+       new_sk->sk_state = LLCP_CONNECTED;
+
+       /* Wake the listening processes */
+       parent->sk_data_ready(parent, 0);
+
+       /* Send CC */
+       nfc_llcp_send_cc(new_sock);
+
+       release_sock(&sock->sk);
+       sock_put(&sock->sk);
+
+       return;
+
+fail:
+       /* Send DM */
+       nfc_llcp_send_dm(local, dsap, ssap, reason);
+
+       return;
+
+}
+
+static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local,
+                               struct sk_buff *skb)
+{
+       struct nfc_llcp_sock *llcp_sock;
+       struct sock *sk;
+       u8 dsap, ssap, ptype, ns, nr;
+
+       ptype = nfc_llcp_ptype(skb);
+       dsap = nfc_llcp_dsap(skb);
+       ssap = nfc_llcp_ssap(skb);
+       ns = nfc_llcp_ns(skb);
+       nr = nfc_llcp_nr(skb);
+
+       pr_debug("%d %d R %d S %d\n", dsap, ssap, nr, ns);
+
+       llcp_sock = nfc_llcp_sock_get(local, dsap, ssap);
+       if (llcp_sock == NULL) {
+               nfc_llcp_send_dm(local, dsap, ssap, LLCP_DM_NOCONN);
+               return;
+       }
+
+       sk = &llcp_sock->sk;
+       lock_sock(sk);
+       if (sk->sk_state == LLCP_CLOSED) {
+               release_sock(sk);
+               nfc_llcp_sock_put(llcp_sock);
+       }
+
+       if (ns == llcp_sock->recv_n)
+               llcp_sock->recv_n = (llcp_sock->recv_n + 1) % 16;
+       else
+               pr_err("Received out of sequence I PDU\n");
+
+       /* Pass the payload upstream */
+       if (ptype == LLCP_PDU_I) {
+               pr_debug("I frame, queueing on %p\n", &llcp_sock->sk);
+
+               skb_pull(skb, LLCP_HEADER_SIZE + LLCP_SEQUENCE_SIZE);
+               if (sock_queue_rcv_skb(&llcp_sock->sk, skb)) {
+                       pr_err("receive queue is full\n");
+                       skb_queue_head(&llcp_sock->tx_backlog_queue, skb);
+               }
+       }
+
+       /* Remove skbs from the pending queue */
+       if (llcp_sock->send_ack_n != nr) {
+               struct sk_buff *s, *tmp;
+
+               llcp_sock->send_ack_n = nr;
+
+               skb_queue_walk_safe(&llcp_sock->tx_pending_queue, s, tmp)
+                       if (nfc_llcp_ns(s) <= nr) {
+                               skb_unlink(s, &llcp_sock->tx_pending_queue);
+                               kfree_skb(s);
+                       }
+       }
+
+       /* Queue some I frames for transmission */
+       while (llcp_sock->remote_ready &&
+               skb_queue_len(&llcp_sock->tx_pending_queue) <= local->remote_rw) {
+               struct sk_buff *pdu, *pending_pdu;
+
+               pdu = skb_dequeue(&llcp_sock->tx_queue);
+               if (pdu == NULL)
+                       break;
+
+               /* Update N(S)/N(R) */
+               nfc_llcp_set_nrns(llcp_sock, pdu);
+
+               pending_pdu = skb_clone(pdu, GFP_KERNEL);
+
+               skb_queue_tail(&local->tx_queue, pdu);
+               skb_queue_tail(&llcp_sock->tx_pending_queue, pending_pdu);
+       }
+
+       release_sock(sk);
+       nfc_llcp_sock_put(llcp_sock);
+}
+
+static void nfc_llcp_recv_disc(struct nfc_llcp_local *local,
+                               struct sk_buff *skb)
+{
+       struct nfc_llcp_sock *llcp_sock;
+       struct sock *sk;
+       u8 dsap, ssap;
+
+       dsap = nfc_llcp_dsap(skb);
+       ssap = nfc_llcp_ssap(skb);
+
+       llcp_sock = nfc_llcp_sock_get(local, dsap, ssap);
+       if (llcp_sock == NULL) {
+               nfc_llcp_send_dm(local, dsap, ssap, LLCP_DM_NOCONN);
+               return;
+       }
+
+       sk = &llcp_sock->sk;
+       lock_sock(sk);
+       if (sk->sk_state == LLCP_CLOSED) {
+               release_sock(sk);
+               nfc_llcp_sock_put(llcp_sock);
+       }
+
+
+       if (sk->sk_state == LLCP_CONNECTED) {
+               nfc_put_device(local->dev);
+               sk->sk_state = LLCP_CLOSED;
+               sk->sk_state_change(sk);
+       }
+
+       nfc_llcp_send_dm(local, dsap, ssap, LLCP_DM_DISC);
+
+       release_sock(sk);
+       nfc_llcp_sock_put(llcp_sock);
+}
+
+static void nfc_llcp_recv_cc(struct nfc_llcp_local *local,
+                               struct sk_buff *skb)
+{
+       struct nfc_llcp_sock *llcp_sock;
+       u8 dsap, ssap;
+
+
+       dsap = nfc_llcp_dsap(skb);
+       ssap = nfc_llcp_ssap(skb);
+
+       llcp_sock = nfc_llcp_sock_get(local, dsap, ssap);
+
+       if (llcp_sock == NULL)
+               llcp_sock = nfc_llcp_sock_get(local, dsap, LLCP_SAP_SDP);
+
+       if (llcp_sock == NULL) {
+               pr_err("Invalid CC\n");
+               nfc_llcp_send_dm(local, dsap, ssap, LLCP_DM_NOCONN);
+
+               return;
+       }
+
+       llcp_sock->dsap = ssap;
+
+       nfc_llcp_parse_tlv(local, &skb->data[LLCP_HEADER_SIZE],
+                               skb->len - LLCP_HEADER_SIZE);
+
+       nfc_llcp_sock_put(llcp_sock);
+}
+
+static void nfc_llcp_rx_work(struct work_struct *work)
+{
+       struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local,
+                                                               rx_work);
+       u8 dsap, ssap, ptype;
+       struct sk_buff *skb;
+
+       skb = local->rx_pending;
+       if (skb == NULL) {
+               pr_debug("No pending SKB\n");
+               return;
+       }
+
+       ptype = nfc_llcp_ptype(skb);
+       dsap = nfc_llcp_dsap(skb);
+       ssap = nfc_llcp_ssap(skb);
+
+       pr_debug("ptype 0x%x dsap 0x%x ssap 0x%x\n", ptype, dsap, ssap);
+
+       switch (ptype) {
+       case LLCP_PDU_SYMM:
+               pr_debug("SYMM\n");
+               break;
+
+       case LLCP_PDU_CONNECT:
+               pr_debug("CONNECT\n");
+               nfc_llcp_recv_connect(local, skb);
+               break;
+
+       case LLCP_PDU_DISC:
+               pr_debug("DISC\n");
+               nfc_llcp_recv_disc(local, skb);
+               break;
+
+       case LLCP_PDU_CC:
+               pr_debug("CC\n");
+               nfc_llcp_recv_cc(local, skb);
+               break;
+
+       case LLCP_PDU_I:
+       case LLCP_PDU_RR:
+               pr_debug("I frame\n");
+               nfc_llcp_recv_hdlc(local, skb);
+               break;
+
+       }
+
+       queue_work(local->tx_wq, &local->tx_work);
+       kfree_skb(local->rx_pending);
+       local->rx_pending = NULL;
+
+       return;
+}
+
+void nfc_llcp_recv(void *data, struct sk_buff *skb, int err)
+{
+       struct nfc_llcp_local *local = (struct nfc_llcp_local *) data;
+
+       pr_debug("Received an LLCP PDU\n");
+       if (err < 0) {
+               pr_err("err %d", err);
+               return;
+       }
+
+       local->rx_pending = skb_get(skb);
+       del_timer(&local->link_timer);
+       queue_work(local->rx_wq, &local->rx_work);
+
+       return;
+}
+
+void nfc_llcp_mac_is_down(struct nfc_dev *dev)
+{
+       struct nfc_llcp_local *local;
+
+       local = nfc_llcp_find_local(dev);
+       if (local == NULL)
+               return;
+
+       /* Close and purge all existing sockets */
+       nfc_llcp_socket_release(local);
+}
+
+void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx,
+                       u8 comm_mode, u8 rf_mode)
+{
+       struct nfc_llcp_local *local;
+
+       pr_debug("rf mode %d\n", rf_mode);
+
+       local = nfc_llcp_find_local(dev);
+       if (local == NULL)
+               return;
+
+       local->target_idx = target_idx;
+       local->comm_mode = comm_mode;
+       local->rf_mode = rf_mode;
+
+       if (rf_mode == NFC_RF_INITIATOR) {
+               pr_debug("Queueing Tx work\n");
+
+               queue_work(local->tx_wq, &local->tx_work);
+       } else {
+               mod_timer(&local->link_timer,
+                       jiffies + msecs_to_jiffies(local->remote_lto));
+       }
+}
+
+int nfc_llcp_register_device(struct nfc_dev *ndev)
+{
+       struct device *dev = &ndev->dev;
+       struct nfc_llcp_local *local;
+       char name[32];
+       int err;
+
+       local = kzalloc(sizeof(struct nfc_llcp_local), GFP_KERNEL);
+       if (local == NULL)
+               return -ENOMEM;
+
+       local->dev = ndev;
+       INIT_LIST_HEAD(&local->list);
+       mutex_init(&local->sdp_lock);
+       mutex_init(&local->socket_lock);
+       init_timer(&local->link_timer);
+       local->link_timer.data = (unsigned long) local;
+       local->link_timer.function = nfc_llcp_symm_timer;
+
+       skb_queue_head_init(&local->tx_queue);
+       INIT_WORK(&local->tx_work, nfc_llcp_tx_work);
+       snprintf(name, sizeof(name), "%s_llcp_tx_wq", dev_name(dev));
+       local->tx_wq = alloc_workqueue(name,
+                       WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
+       if (local->tx_wq == NULL) {
+               err = -ENOMEM;
+               goto err_local;
+       }
+
+       local->rx_pending = NULL;
+       INIT_WORK(&local->rx_work, nfc_llcp_rx_work);
+       snprintf(name, sizeof(name), "%s_llcp_rx_wq", dev_name(dev));
+       local->rx_wq = alloc_workqueue(name,
+                       WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
+       if (local->rx_wq == NULL) {
+               err = -ENOMEM;
+               goto err_tx_wq;
+       }
+
+       INIT_WORK(&local->timeout_work, nfc_llcp_timeout_work);
+       snprintf(name, sizeof(name), "%s_llcp_timeout_wq", dev_name(dev));
+       local->timeout_wq = alloc_workqueue(name,
+                       WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
+       if (local->timeout_wq == NULL) {
+               err = -ENOMEM;
+               goto err_rx_wq;
+       }
+
+       nfc_llcp_build_gb(local);
+
+       local->remote_miu = LLCP_DEFAULT_MIU;
+       local->remote_lto = LLCP_DEFAULT_LTO;
+       local->remote_rw = LLCP_DEFAULT_RW;
+
+       list_add(&llcp_devices, &local->list);
+
+       return 0;
+
+err_rx_wq:
+       destroy_workqueue(local->rx_wq);
+
+err_tx_wq:
+       destroy_workqueue(local->tx_wq);
+
+err_local:
+       kfree(local);
+
+       return 0;
+}
+
+void nfc_llcp_unregister_device(struct nfc_dev *dev)
+{
+       struct nfc_llcp_local *local = nfc_llcp_find_local(dev);
+
+       if (local == NULL) {
+               pr_debug("No such device\n");
+               return;
+       }
+
+       list_del(&local->list);
+       nfc_llcp_socket_release(local);
+       del_timer_sync(&local->link_timer);
+       skb_queue_purge(&local->tx_queue);
+       destroy_workqueue(local->tx_wq);
+       destroy_workqueue(local->rx_wq);
+       kfree(local->rx_pending);
+       kfree(local);
+}
+
+int __init nfc_llcp_init(void)
+{
+       INIT_LIST_HEAD(&llcp_devices);
+
+       return nfc_llcp_sock_init();
+}
+
+void nfc_llcp_exit(void)
+{
+       nfc_llcp_sock_exit();
+}
diff --git a/net/nfc/llcp/llcp.h b/net/nfc/llcp/llcp.h
new file mode 100644 (file)
index 0000000..0ad2e33
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2011  Intel Corporation. All rights reserved.
+ *
+ * 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; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+enum llcp_state {
+       LLCP_CONNECTED = 1, /* wait_for_packet() wants that */
+       LLCP_CLOSED,
+       LLCP_BOUND,
+       LLCP_LISTEN,
+};
+
+#define LLCP_DEFAULT_LTO 100
+#define LLCP_DEFAULT_RW  1
+#define LLCP_DEFAULT_MIU 128
+
+#define LLCP_WKS_NUM_SAP   16
+#define LLCP_SDP_NUM_SAP   16
+#define LLCP_LOCAL_NUM_SAP 32
+#define LLCP_LOCAL_SAP_OFFSET (LLCP_WKS_NUM_SAP + LLCP_SDP_NUM_SAP)
+#define LLCP_MAX_SAP (LLCP_WKS_NUM_SAP + LLCP_SDP_NUM_SAP + LLCP_LOCAL_NUM_SAP)
+
+struct nfc_llcp_sock;
+
+struct nfc_llcp_local {
+       struct list_head list;
+       struct nfc_dev *dev;
+
+       struct mutex sdp_lock;
+       struct mutex socket_lock;
+
+       struct timer_list link_timer;
+       struct sk_buff_head tx_queue;
+       struct workqueue_struct *tx_wq;
+       struct work_struct       tx_work;
+       struct workqueue_struct *rx_wq;
+       struct work_struct       rx_work;
+       struct sk_buff *rx_pending;
+       struct workqueue_struct *timeout_wq;
+       struct work_struct       timeout_work;
+
+       u32 target_idx;
+       u8 rf_mode;
+       u8 comm_mode;
+       unsigned long local_wks;      /* Well known services */
+       unsigned long local_sdp;      /* Local services  */
+       unsigned long local_sap; /* Local SAPs, not available for discovery */
+
+       /* local */
+       u8 gb[NFC_MAX_GT_LEN];
+       u8 gb_len;
+
+       /* remote */
+       u8 remote_gb[NFC_MAX_GT_LEN];
+       u8 remote_gb_len;
+
+       u8  remote_version;
+       u16 remote_miu;
+       u16 remote_lto;
+       u8  remote_opt;
+       u16 remote_wks;
+       u8  remote_rw;
+
+       /* sockets array */
+       struct nfc_llcp_sock *sockets[LLCP_MAX_SAP];
+};
+
+struct nfc_llcp_sock {
+       struct sock sk;
+       struct list_head list;
+       struct nfc_dev *dev;
+       struct nfc_llcp_local *local;
+       u32 target_idx;
+       u32 nfc_protocol;
+
+       u8 ssap;
+       u8 dsap;
+       char *service_name;
+       size_t service_name_len;
+
+       /* Link variables */
+       u8 send_n;
+       u8 send_ack_n;
+       u8 recv_n;
+       u8 recv_ack_n;
+
+       /* Is the remote peer ready to receive */
+       u8 remote_ready;
+
+       struct sk_buff_head tx_queue;
+       struct sk_buff_head tx_pending_queue;
+       struct sk_buff_head tx_backlog_queue;
+
+       struct list_head accept_queue;
+       struct sock *parent;
+};
+
+#define nfc_llcp_sock(sk) ((struct nfc_llcp_sock *) (sk))
+#define nfc_llcp_dev(sk)  (nfc_llcp_sock((sk))->dev)
+
+#define LLCP_HEADER_SIZE   2
+#define LLCP_SEQUENCE_SIZE 1
+
+/* LLCP versions: 1.1 is 1.0 plus SDP */
+#define LLCP_VERSION_10 0x10
+#define LLCP_VERSION_11 0x11
+
+/* LLCP PDU types */
+#define LLCP_PDU_SYMM     0x0
+#define LLCP_PDU_PAX      0x1
+#define LLCP_PDU_AGF      0x2
+#define LLCP_PDU_UI       0x3
+#define LLCP_PDU_CONNECT  0x4
+#define LLCP_PDU_DISC     0x5
+#define LLCP_PDU_CC       0x6
+#define LLCP_PDU_DM       0x7
+#define LLCP_PDU_FRMR     0x8
+#define LLCP_PDU_SNL      0x9
+#define LLCP_PDU_I        0xc
+#define LLCP_PDU_RR       0xd
+#define LLCP_PDU_RNR      0xe
+
+/* Parameters TLV types */
+#define LLCP_TLV_VERSION 0x1
+#define LLCP_TLV_MIUX    0x2
+#define LLCP_TLV_WKS     0x3
+#define LLCP_TLV_LTO     0x4
+#define LLCP_TLV_RW      0x5
+#define LLCP_TLV_SN      0x6
+#define LLCP_TLV_OPT     0x7
+#define LLCP_TLV_SDREQ   0x8
+#define LLCP_TLV_SDRES   0x9
+#define LLCP_TLV_MAX     0xa
+
+/* Well known LLCP SAP */
+#define LLCP_SAP_SDP   0x1
+#define LLCP_SAP_IP    0x2
+#define LLCP_SAP_OBEX  0x3
+#define LLCP_SAP_SNEP  0x4
+#define LLCP_SAP_MAX   0xff
+
+/* Disconnection reason code */
+#define LLCP_DM_DISC    0x00
+#define LLCP_DM_NOCONN  0x01
+#define LLCP_DM_NOBOUND 0x02
+#define LLCP_DM_REJ     0x03
+
+
+struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev);
+u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local,
+                               struct nfc_llcp_sock *sock);
+u8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local);
+void nfc_llcp_put_ssap(struct nfc_llcp_local *local, u8 ssap);
+
+/* Sock API */
+struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp);
+void nfc_llcp_sock_free(struct nfc_llcp_sock *sock);
+void nfc_llcp_accept_unlink(struct sock *sk);
+void nfc_llcp_accept_enqueue(struct sock *parent, struct sock *sk);
+struct sock *nfc_llcp_accept_dequeue(struct sock *sk, struct socket *newsock);
+
+/* TLV API */
+int nfc_llcp_parse_tlv(struct nfc_llcp_local *local,
+                       u8 *tlv_array, u16 tlv_array_len);
+
+/* Commands API */
+void nfc_llcp_recv(void *data, struct sk_buff *skb, int err);
+u8 *nfc_llcp_build_tlv(u8 type, u8 *value, u8 value_length, u8 *tlv_length);
+void nfc_llcp_recv(void *data, struct sk_buff *skb, int err);
+int nfc_llcp_disconnect(struct nfc_llcp_sock *sock);
+int nfc_llcp_send_symm(struct nfc_dev *dev);
+int nfc_llcp_send_connect(struct nfc_llcp_sock *sock);
+int nfc_llcp_send_cc(struct nfc_llcp_sock *sock);
+int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason);
+int nfc_llcp_send_disconnect(struct nfc_llcp_sock *sock);
+
+/* Socket API */
+int __init nfc_llcp_sock_init(void);
+void nfc_llcp_sock_exit(void);
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c
new file mode 100644 (file)
index 0000000..f738ccd
--- /dev/null
@@ -0,0 +1,675 @@
+/*
+ * Copyright (C) 2011  Intel Corporation. All rights reserved.
+ *
+ * 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; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define pr_fmt(fmt) "llcp: %s: " fmt, __func__
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/nfc.h>
+
+#include "../nfc.h"
+#include "llcp.h"
+
+static struct proto llcp_sock_proto = {
+       .name     = "NFC_LLCP",
+       .owner    = THIS_MODULE,
+       .obj_size = sizeof(struct nfc_llcp_sock),
+};
+
+static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
+{
+       struct sock *sk = sock->sk;
+       struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
+       struct nfc_llcp_local *local;
+       struct nfc_dev *dev;
+       struct sockaddr_nfc_llcp llcp_addr;
+       int len, ret = 0;
+
+       pr_debug("sk %p addr %p family %d\n", sk, addr, addr->sa_family);
+
+       if (!addr || addr->sa_family != AF_NFC)
+               return -EINVAL;
+
+       memset(&llcp_addr, 0, sizeof(llcp_addr));
+       len = min_t(unsigned int, sizeof(llcp_addr), alen);
+       memcpy(&llcp_addr, addr, len);
+
+       /* This is going to be a listening socket, dsap must be 0 */
+       if (llcp_addr.dsap != 0)
+               return -EINVAL;
+
+       lock_sock(sk);
+
+       if (sk->sk_state != LLCP_CLOSED) {
+               ret = -EBADFD;
+               goto error;
+       }
+
+       dev = nfc_get_device(llcp_addr.dev_idx);
+       if (dev == NULL) {
+               ret = -ENODEV;
+               goto error;
+       }
+
+       local = nfc_llcp_find_local(dev);
+       if (local == NULL) {
+               ret = -ENODEV;
+               goto put_dev;
+       }
+
+       llcp_sock->dev = dev;
+       llcp_sock->local = local;
+       llcp_sock->nfc_protocol = llcp_addr.nfc_protocol;
+       llcp_sock->service_name_len = min_t(unsigned int,
+                       llcp_addr.service_name_len, NFC_LLCP_MAX_SERVICE_NAME);
+       llcp_sock->service_name = kmemdup(llcp_addr.service_name,
+                               llcp_sock->service_name_len, GFP_KERNEL);
+
+       llcp_sock->ssap = nfc_llcp_get_sdp_ssap(local, llcp_sock);
+       if (llcp_sock->ssap == LLCP_MAX_SAP)
+               goto put_dev;
+
+       local->sockets[llcp_sock->ssap] = llcp_sock;
+
+       pr_debug("Socket bound to SAP %d\n", llcp_sock->ssap);
+
+       sk->sk_state = LLCP_BOUND;
+
+put_dev:
+       nfc_put_device(dev);
+
+error:
+       release_sock(sk);
+       return ret;
+}
+
+static int llcp_sock_listen(struct socket *sock, int backlog)
+{
+       struct sock *sk = sock->sk;
+       int ret = 0;
+
+       pr_debug("sk %p backlog %d\n", sk, backlog);
+
+       lock_sock(sk);
+
+       if ((sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM)
+                       || sk->sk_state != LLCP_BOUND) {
+               ret = -EBADFD;
+               goto error;
+       }
+
+       sk->sk_max_ack_backlog = backlog;
+       sk->sk_ack_backlog = 0;
+
+       pr_debug("Socket listening\n");
+       sk->sk_state = LLCP_LISTEN;
+
+error:
+       release_sock(sk);
+
+       return ret;
+}
+
+void nfc_llcp_accept_unlink(struct sock *sk)
+{
+       struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
+
+       pr_debug("state %d\n", sk->sk_state);
+
+       list_del_init(&llcp_sock->accept_queue);
+       sk_acceptq_removed(llcp_sock->parent);
+       llcp_sock->parent = NULL;
+
+       sock_put(sk);
+}
+
+void nfc_llcp_accept_enqueue(struct sock *parent, struct sock *sk)
+{
+       struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
+       struct nfc_llcp_sock *llcp_sock_parent = nfc_llcp_sock(parent);
+
+       /* Lock will be free from unlink */
+       sock_hold(sk);
+
+       list_add_tail(&llcp_sock->accept_queue,
+                       &llcp_sock_parent->accept_queue);
+       llcp_sock->parent = parent;
+       sk_acceptq_added(parent);
+}
+
+struct sock *nfc_llcp_accept_dequeue(struct sock *parent,
+                                       struct socket *newsock)
+{
+       struct nfc_llcp_sock *lsk, *n, *llcp_parent;
+       struct sock *sk;
+
+       llcp_parent = nfc_llcp_sock(parent);
+
+       list_for_each_entry_safe(lsk, n, &llcp_parent->accept_queue,
+                                                       accept_queue) {
+               sk = &lsk->sk;
+               lock_sock(sk);
+
+               if (sk->sk_state == LLCP_CLOSED) {
+                       release_sock(sk);
+                       nfc_llcp_accept_unlink(sk);
+                       continue;
+               }
+
+               if (sk->sk_state == LLCP_CONNECTED || !newsock) {
+                       nfc_llcp_accept_unlink(sk);
+                       if (newsock)
+                               sock_graft(sk, newsock);
+
+                       release_sock(sk);
+
+                       pr_debug("Returning sk state %d\n", sk->sk_state);
+
+                       return sk;
+               }
+
+               release_sock(sk);
+       }
+
+       return NULL;
+}
+
+static int llcp_sock_accept(struct socket *sock, struct socket *newsock,
+                                                               int flags)
+{
+       DECLARE_WAITQUEUE(wait, current);
+       struct sock *sk = sock->sk, *new_sk;
+       long timeo;
+       int ret = 0;
+
+       pr_debug("parent %p\n", sk);
+
+       lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
+
+       if (sk->sk_state != LLCP_LISTEN) {
+               ret = -EBADFD;
+               goto error;
+       }
+
+       timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
+
+       /* Wait for an incoming connection. */
+       add_wait_queue_exclusive(sk_sleep(sk), &wait);
+       while (!(new_sk = nfc_llcp_accept_dequeue(sk, newsock))) {
+               set_current_state(TASK_INTERRUPTIBLE);
+
+               if (!timeo) {
+                       ret = -EAGAIN;
+                       break;
+               }
+
+               if (signal_pending(current)) {
+                       ret = sock_intr_errno(timeo);
+                       break;
+               }
+
+               release_sock(sk);
+               timeo = schedule_timeout(timeo);
+               lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
+       }
+       __set_current_state(TASK_RUNNING);
+       remove_wait_queue(sk_sleep(sk), &wait);
+
+       if (ret)
+               goto error;
+
+       newsock->state = SS_CONNECTED;
+
+       pr_debug("new socket %p\n", new_sk);
+
+error:
+       release_sock(sk);
+
+       return ret;
+}
+
+static int llcp_sock_getname(struct socket *sock, struct sockaddr *addr,
+                            int *len, int peer)
+{
+       struct sockaddr_nfc_llcp *llcp_addr = (struct sockaddr_nfc_llcp *) addr;
+       struct sock *sk = sock->sk;
+       struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
+
+       pr_debug("%p\n", sk);
+
+       addr->sa_family = AF_NFC;
+       *len = sizeof(struct sockaddr_nfc_llcp);
+
+       llcp_addr->dev_idx = llcp_sock->dev->idx;
+       llcp_addr->dsap = llcp_sock->dsap;
+       llcp_addr->ssap = llcp_sock->ssap;
+       llcp_addr->service_name_len = llcp_sock->service_name_len;
+       memcpy(llcp_addr->service_name, llcp_sock->service_name,
+                                       llcp_addr->service_name_len);
+
+       return 0;
+}
+
+static inline unsigned int llcp_accept_poll(struct sock *parent)
+{
+       struct nfc_llcp_sock *llcp_sock, *n, *parent_sock;
+       struct sock *sk;
+
+       parent_sock = nfc_llcp_sock(parent);
+
+       list_for_each_entry_safe(llcp_sock, n, &parent_sock->accept_queue,
+                                                               accept_queue) {
+               sk = &llcp_sock->sk;
+
+               if (sk->sk_state == LLCP_CONNECTED)
+                       return POLLIN | POLLRDNORM;
+       }
+
+       return 0;
+}
+
+static unsigned int llcp_sock_poll(struct file *file, struct socket *sock,
+                                                       poll_table *wait)
+{
+       struct sock *sk = sock->sk;
+       unsigned int mask = 0;
+
+       pr_debug("%p\n", sk);
+
+       sock_poll_wait(file, sk_sleep(sk), wait);
+
+       if (sk->sk_state == LLCP_LISTEN)
+               return llcp_accept_poll(sk);
+
+       if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
+               mask |= POLLERR;
+
+       if (!skb_queue_empty(&sk->sk_receive_queue))
+               mask |= POLLIN;
+
+       if (sk->sk_state == LLCP_CLOSED)
+               mask |= POLLHUP;
+
+       return mask;
+}
+
+static int llcp_sock_release(struct socket *sock)
+{
+       struct sock *sk = sock->sk;
+       struct nfc_llcp_local *local;
+       struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
+
+       if (!sk)
+               return 0;
+
+       pr_debug("%p\n", sk);
+
+       local = llcp_sock->local;
+       if (local == NULL)
+               return -ENODEV;
+
+       mutex_lock(&local->socket_lock);
+
+       if (llcp_sock == local->sockets[llcp_sock->ssap]) {
+               local->sockets[llcp_sock->ssap] = NULL;
+       } else {
+               struct nfc_llcp_sock *parent, *s, *n;
+
+               parent = local->sockets[llcp_sock->ssap];
+
+               list_for_each_entry_safe(s, n, &parent->list, list)
+                       if (llcp_sock == s) {
+                               list_del(&s->list);
+                               break;
+                       }
+
+       }
+
+       mutex_unlock(&local->socket_lock);
+
+       lock_sock(sk);
+
+       /* Send a DISC */
+       if (sk->sk_state == LLCP_CONNECTED)
+               nfc_llcp_disconnect(llcp_sock);
+
+       if (sk->sk_state == LLCP_LISTEN) {
+               struct nfc_llcp_sock *lsk, *n;
+               struct sock *accept_sk;
+
+               list_for_each_entry_safe(lsk, n, &llcp_sock->accept_queue,
+                                                               accept_queue) {
+                       accept_sk = &lsk->sk;
+                       lock_sock(accept_sk);
+
+                       nfc_llcp_disconnect(lsk);
+                       nfc_llcp_accept_unlink(accept_sk);
+
+                       release_sock(accept_sk);
+
+                       sock_set_flag(sk, SOCK_DEAD);
+                       sock_orphan(accept_sk);
+                       sock_put(accept_sk);
+               }
+       }
+
+       /* Freeing the SAP */
+       if ((sk->sk_state == LLCP_CONNECTED
+                       && llcp_sock->ssap > LLCP_LOCAL_SAP_OFFSET) ||
+           sk->sk_state == LLCP_BOUND ||
+           sk->sk_state == LLCP_LISTEN)
+               nfc_llcp_put_ssap(llcp_sock->local, llcp_sock->ssap);
+
+       sock_set_flag(sk, SOCK_DEAD);
+
+       release_sock(sk);
+
+       sock_orphan(sk);
+       sock_put(sk);
+
+       return 0;
+}
+
+static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
+                                                       int len, int flags)
+{
+       struct sock *sk = sock->sk;
+       struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
+       struct sockaddr_nfc_llcp *addr = (struct sockaddr_nfc_llcp *)_addr;
+       struct nfc_dev *dev;
+       struct nfc_llcp_local *local;
+       int ret = 0;
+
+       pr_debug("sock %p sk %p flags 0x%x\n", sock, sk, flags);
+
+       if (!addr || len < sizeof(struct sockaddr_nfc) ||
+                       addr->sa_family != AF_NFC) {
+               pr_err("Invalid socket\n");
+               return -EINVAL;
+       }
+
+       if (addr->service_name_len == 0 && addr->dsap == 0) {
+               pr_err("Missing service name or dsap\n");
+               return -EINVAL;
+       }
+
+       pr_debug("addr dev_idx=%u target_idx=%u protocol=%u\n", addr->dev_idx,
+                                       addr->target_idx, addr->nfc_protocol);
+
+       lock_sock(sk);
+
+       if (sk->sk_state == LLCP_CONNECTED) {
+               ret = -EISCONN;
+               goto error;
+       }
+
+       dev = nfc_get_device(addr->dev_idx);
+       if (dev == NULL) {
+               ret = -ENODEV;
+               goto error;
+       }
+
+       local = nfc_llcp_find_local(dev);
+       if (local == NULL) {
+               ret = -ENODEV;
+               goto put_dev;
+       }
+
+       device_lock(&dev->dev);
+       if (dev->dep_link_up == false) {
+               ret = -ENOLINK;
+               device_unlock(&dev->dev);
+               goto put_dev;
+       }
+       device_unlock(&dev->dev);
+
+       if (local->rf_mode == NFC_RF_INITIATOR &&
+                       addr->target_idx != local->target_idx) {
+               ret = -ENOLINK;
+               goto put_dev;
+       }
+
+       llcp_sock->dev = dev;
+       llcp_sock->local = local;
+       llcp_sock->ssap = nfc_llcp_get_local_ssap(local);
+       if (llcp_sock->ssap == LLCP_SAP_MAX) {
+               ret = -ENOMEM;
+               goto put_dev;
+       }
+       if (addr->service_name_len == 0)
+               llcp_sock->dsap = addr->dsap;
+       else
+               llcp_sock->dsap = LLCP_SAP_SDP;
+       llcp_sock->nfc_protocol = addr->nfc_protocol;
+       llcp_sock->service_name_len = min_t(unsigned int,
+                       addr->service_name_len, NFC_LLCP_MAX_SERVICE_NAME);
+       llcp_sock->service_name = kmemdup(addr->service_name,
+                                llcp_sock->service_name_len, GFP_KERNEL);
+
+       local->sockets[llcp_sock->ssap] = llcp_sock;
+
+       ret = nfc_llcp_send_connect(llcp_sock);
+       if (ret)
+               goto put_dev;
+
+       sk->sk_state = LLCP_CONNECTED;
+
+       release_sock(sk);
+       return 0;
+
+put_dev:
+       nfc_put_device(dev);
+
+error:
+       release_sock(sk);
+       return ret;
+}
+
+static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
+                            struct msghdr *msg, size_t len, int flags)
+{
+       int noblock = flags & MSG_DONTWAIT;
+       struct sock *sk = sock->sk;
+       unsigned int copied, rlen;
+       struct sk_buff *skb, *cskb;
+       int err = 0;
+
+       pr_debug("%p %zu\n", sk, len);
+
+       lock_sock(sk);
+
+       if (sk->sk_state == LLCP_CLOSED &&
+                       skb_queue_empty(&sk->sk_receive_queue)) {
+               release_sock(sk);
+               return 0;
+       }
+
+       release_sock(sk);
+
+       if (flags & (MSG_OOB))
+               return -EOPNOTSUPP;
+
+       skb = skb_recv_datagram(sk, flags, noblock, &err);
+       if (!skb) {
+               pr_err("Recv datagram failed state %d %d %d",
+                               sk->sk_state, err, sock_error(sk));
+
+               if (sk->sk_shutdown & RCV_SHUTDOWN)
+                       return 0;
+
+               return err;
+       }
+
+       rlen   = skb->len;              /* real length of skb */
+       copied = min_t(unsigned int, rlen, len);
+
+       cskb = skb;
+       if (memcpy_toiovec(msg->msg_iov, cskb->data, copied)) {
+               if (!(flags & MSG_PEEK))
+                       skb_queue_head(&sk->sk_receive_queue, skb);
+               return -EFAULT;
+       }
+
+       /* Mark read part of skb as used */
+       if (!(flags & MSG_PEEK)) {
+
+               /* SOCK_STREAM: re-queue skb if it contains unreceived data */
+               if (sk->sk_type == SOCK_STREAM) {
+                       skb_pull(skb, copied);
+                       if (skb->len) {
+                               skb_queue_head(&sk->sk_receive_queue, skb);
+                               goto done;
+                       }
+               }
+
+               kfree_skb(skb);
+       }
+
+       /* XXX Queue backlogged skbs */
+
+done:
+       /* SOCK_SEQPACKET: return real length if MSG_TRUNC is set */
+       if (sk->sk_type == SOCK_SEQPACKET && (flags & MSG_TRUNC))
+               copied = rlen;
+
+       return copied;
+}
+
+static const struct proto_ops llcp_sock_ops = {
+       .family         = PF_NFC,
+       .owner          = THIS_MODULE,
+       .bind           = llcp_sock_bind,
+       .connect        = llcp_sock_connect,
+       .release        = llcp_sock_release,
+       .socketpair     = sock_no_socketpair,
+       .accept         = llcp_sock_accept,
+       .getname        = llcp_sock_getname,
+       .poll           = llcp_sock_poll,
+       .ioctl          = sock_no_ioctl,
+       .listen         = llcp_sock_listen,
+       .shutdown       = sock_no_shutdown,
+       .setsockopt     = sock_no_setsockopt,
+       .getsockopt     = sock_no_getsockopt,
+       .sendmsg        = sock_no_sendmsg,
+       .recvmsg        = llcp_sock_recvmsg,
+       .mmap           = sock_no_mmap,
+};
+
+static void llcp_sock_destruct(struct sock *sk)
+{
+       struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
+
+       pr_debug("%p\n", sk);
+
+       if (sk->sk_state == LLCP_CONNECTED)
+               nfc_put_device(llcp_sock->dev);
+
+       skb_queue_purge(&sk->sk_receive_queue);
+
+       nfc_llcp_sock_free(llcp_sock);
+
+       if (!sock_flag(sk, SOCK_DEAD)) {
+               pr_err("Freeing alive NFC LLCP socket %p\n", sk);
+               return;
+       }
+}
+
+struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp)
+{
+       struct sock *sk;
+       struct nfc_llcp_sock *llcp_sock;
+
+       sk = sk_alloc(&init_net, PF_NFC, gfp, &llcp_sock_proto);
+       if (!sk)
+               return NULL;
+
+       llcp_sock = nfc_llcp_sock(sk);
+
+       sock_init_data(sock, sk);
+       sk->sk_state = LLCP_CLOSED;
+       sk->sk_protocol = NFC_SOCKPROTO_LLCP;
+       sk->sk_type = type;
+       sk->sk_destruct = llcp_sock_destruct;
+
+       llcp_sock->ssap = 0;
+       llcp_sock->dsap = LLCP_SAP_SDP;
+       llcp_sock->send_n = llcp_sock->send_ack_n = 0;
+       llcp_sock->recv_n = llcp_sock->recv_ack_n = 0;
+       llcp_sock->remote_ready = 1;
+       skb_queue_head_init(&llcp_sock->tx_queue);
+       skb_queue_head_init(&llcp_sock->tx_pending_queue);
+       skb_queue_head_init(&llcp_sock->tx_backlog_queue);
+       INIT_LIST_HEAD(&llcp_sock->list);
+       INIT_LIST_HEAD(&llcp_sock->accept_queue);
+
+       if (sock != NULL)
+               sock->state = SS_UNCONNECTED;
+
+       return sk;
+}
+
+void nfc_llcp_sock_free(struct nfc_llcp_sock *sock)
+{
+       kfree(sock->service_name);
+
+       skb_queue_purge(&sock->tx_queue);
+       skb_queue_purge(&sock->tx_pending_queue);
+       skb_queue_purge(&sock->tx_backlog_queue);
+
+       list_del_init(&sock->accept_queue);
+
+       sock->parent = NULL;
+}
+
+static int llcp_sock_create(struct net *net, struct socket *sock,
+                               const struct nfc_protocol *nfc_proto)
+{
+       struct sock *sk;
+
+       pr_debug("%p\n", sock);
+
+       if (sock->type != SOCK_STREAM && sock->type != SOCK_DGRAM)
+               return -ESOCKTNOSUPPORT;
+
+       sock->ops = &llcp_sock_ops;
+
+       sk = nfc_llcp_sock_alloc(sock, sock->type, GFP_ATOMIC);
+       if (sk == NULL)
+               return -ENOMEM;
+
+       return 0;
+}
+
+static const struct nfc_protocol llcp_nfc_proto = {
+       .id       = NFC_SOCKPROTO_LLCP,
+       .proto    = &llcp_sock_proto,
+       .owner    = THIS_MODULE,
+       .create   = llcp_sock_create
+};
+
+int __init nfc_llcp_sock_init(void)
+{
+       return nfc_proto_register(&llcp_nfc_proto);
+}
+
+void nfc_llcp_sock_exit(void)
+{
+       nfc_proto_unregister(&llcp_nfc_proto);
+}
index 37de28e973309f8efa4089e64f74b35041a325ea..2deb4aebf5684fcc736299270007ec5741b78846 100644 (file)
@@ -25,7 +25,7 @@
  *
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__
 
 #include <linux/types.h>
 #include <linux/workqueue.h>
@@ -71,7 +71,7 @@ static int __nci_request(struct nci_dev *ndev,
        __u32 timeout)
 {
        int rc = 0;
-       unsigned long completion_rc;
+       long completion_rc;
 
        ndev->req_status = NCI_REQ_PEND;
 
index 1e040feb2f84c328113b6248ddae42c55e00b2d6..e5756b30e6025ff6e90a6419824c6e9c378131bd 100644 (file)
@@ -21,7 +21,7 @@
  *
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__
 
 #include <linux/types.h>
 #include <linux/interrupt.h>
index c36bd4a09abbc15f761616689efbd6c80afa3850..003846b2c326c966ace39602da807ec0c2ef52bf 100644 (file)
@@ -25,7 +25,7 @@
  *
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__
 
 #include <linux/types.h>
 #include <linux/interrupt.h>
index ca611c52aaaaf628f63b66f16d692d73906db5ec..3f444c8a66e93480de2dfa1ade7f86d3b4fbf813 100644 (file)
@@ -25,7 +25,7 @@
  *
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__
 
 #include <linux/types.h>
 #include <linux/interrupt.h>
index c10e9b8c5ad9e094dae0d33ebff234ffc84036dd..43a1c47756a7dd18391f442373a45c811bc5fd03 100644 (file)
@@ -21,7 +21,7 @@
  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__
 
 #include <net/genetlink.h>
 #include <linux/nfc.h>
@@ -46,6 +46,8 @@ static const struct nla_policy nfc_genl_policy[NFC_ATTR_MAX + 1] = {
        [NFC_ATTR_DEVICE_NAME] = { .type = NLA_STRING,
                                .len = NFC_DEVICE_NAME_MAXSIZE },
        [NFC_ATTR_PROTOCOLS] = { .type = NLA_U32 },
+       [NFC_ATTR_COMM_MODE] = { .type = NLA_U8 },
+       [NFC_ATTR_RF_MODE] = { .type = NLA_U8 },
 };
 
 static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target,
@@ -311,6 +313,75 @@ static int nfc_genl_dump_devices_done(struct netlink_callback *cb)
        return 0;
 }
 
+int nfc_genl_dep_link_up_event(struct nfc_dev *dev, u32 target_idx,
+                                               u8 comm_mode, u8 rf_mode)
+{
+       struct sk_buff *msg;
+       void *hdr;
+
+       pr_debug("DEP link is up\n");
+
+       msg = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC);
+       if (!msg)
+               return -ENOMEM;
+
+       hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0,
+                               NFC_CMD_DEP_LINK_UP);
+       if (!hdr)
+               goto free_msg;
+
+       NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx);
+       if (rf_mode == NFC_RF_INITIATOR)
+               NLA_PUT_U32(msg, NFC_ATTR_TARGET_INDEX, target_idx);
+       NLA_PUT_U8(msg, NFC_ATTR_COMM_MODE, comm_mode);
+       NLA_PUT_U8(msg, NFC_ATTR_RF_MODE, rf_mode);
+
+       genlmsg_end(msg, hdr);
+
+       dev->dep_link_up = true;
+
+       genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_ATOMIC);
+
+       return 0;
+
+nla_put_failure:
+       genlmsg_cancel(msg, hdr);
+free_msg:
+       nlmsg_free(msg);
+       return -EMSGSIZE;
+}
+
+int nfc_genl_dep_link_down_event(struct nfc_dev *dev)
+{
+       struct sk_buff *msg;
+       void *hdr;
+
+       pr_debug("DEP link is down\n");
+
+       msg = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC);
+       if (!msg)
+               return -ENOMEM;
+
+       hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0,
+                               NFC_CMD_DEP_LINK_DOWN);
+       if (!hdr)
+               goto free_msg;
+
+       NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx);
+
+       genlmsg_end(msg, hdr);
+
+       genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_ATOMIC);
+
+       return 0;
+
+nla_put_failure:
+       genlmsg_cancel(msg, hdr);
+free_msg:
+       nlmsg_free(msg);
+       return -EMSGSIZE;
+}
+
 static int nfc_genl_get_device(struct sk_buff *skb, struct genl_info *info)
 {
        struct sk_buff *msg;
@@ -398,6 +469,8 @@ static int nfc_genl_start_poll(struct sk_buff *skb, struct genl_info *info)
        u32 idx;
        u32 protocols;
 
+       pr_debug("Poll start\n");
+
        if (!info->attrs[NFC_ATTR_DEVICE_INDEX] ||
                !info->attrs[NFC_ATTR_PROTOCOLS])
                return -EINVAL;
@@ -452,6 +525,67 @@ out:
        return rc;
 }
 
+static int nfc_genl_dep_link_up(struct sk_buff *skb, struct genl_info *info)
+{
+       struct nfc_dev *dev;
+       int rc, tgt_idx;
+       u32 idx;
+       u8 comm, rf;
+
+       pr_debug("DEP link up\n");
+
+       if (!info->attrs[NFC_ATTR_DEVICE_INDEX] ||
+                       !info->attrs[NFC_ATTR_COMM_MODE] ||
+                       !info->attrs[NFC_ATTR_RF_MODE])
+               return -EINVAL;
+
+       idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
+       if (!info->attrs[NFC_ATTR_TARGET_INDEX])
+               tgt_idx = NFC_TARGET_IDX_ANY;
+       else
+               tgt_idx = nla_get_u32(info->attrs[NFC_ATTR_TARGET_INDEX]);
+
+       comm = nla_get_u8(info->attrs[NFC_ATTR_COMM_MODE]);
+       rf = nla_get_u8(info->attrs[NFC_ATTR_RF_MODE]);
+
+       if (comm != NFC_COMM_ACTIVE && comm != NFC_COMM_PASSIVE)
+               return -EINVAL;
+
+       if (rf != NFC_RF_INITIATOR && comm != NFC_RF_TARGET)
+               return -EINVAL;
+
+       dev = nfc_get_device(idx);
+       if (!dev)
+               return -ENODEV;
+
+       rc = nfc_dep_link_up(dev, tgt_idx, comm, rf);
+
+       nfc_put_device(dev);
+
+       return rc;
+}
+
+static int nfc_genl_dep_link_down(struct sk_buff *skb, struct genl_info *info)
+{
+       struct nfc_dev *dev;
+       int rc;
+       u32 idx;
+
+       if (!info->attrs[NFC_ATTR_DEVICE_INDEX])
+               return -EINVAL;
+
+       idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
+
+       dev = nfc_get_device(idx);
+       if (!dev)
+               return -ENODEV;
+
+       rc = nfc_dep_link_down(dev);
+
+       nfc_put_device(dev);
+       return rc;
+}
+
 static struct genl_ops nfc_genl_ops[] = {
        {
                .cmd = NFC_CMD_GET_DEVICE,
@@ -480,6 +614,16 @@ static struct genl_ops nfc_genl_ops[] = {
                .doit = nfc_genl_stop_poll,
                .policy = nfc_genl_policy,
        },
+       {
+               .cmd = NFC_CMD_DEP_LINK_UP,
+               .doit = nfc_genl_dep_link_up,
+               .policy = nfc_genl_policy,
+       },
+       {
+               .cmd = NFC_CMD_DEP_LINK_DOWN,
+               .doit = nfc_genl_dep_link_down,
+               .policy = nfc_genl_policy,
+       },
        {
                .cmd = NFC_CMD_GET_TARGET,
                .dumpit = nfc_genl_dump_targets,
@@ -504,12 +648,10 @@ static int nfc_genl_rcv_nl_event(struct notifier_block *this,
        dev = nfc_device_iter_next(&iter);
 
        while (dev) {
-               mutex_lock(&dev->genl_data.genl_data_mutex);
                if (dev->genl_data.poll_req_pid == n->pid) {
                        nfc_stop_poll(dev);
                        dev->genl_data.poll_req_pid = 0;
                }
-               mutex_unlock(&dev->genl_data.genl_data_mutex);
                dev = nfc_device_iter_next(&iter);
        }
 
index 67d605015304ce035bef970d1c05697e60b8155b..2c2c4015c68b61be5121df63e6c9130c302c9275 100644 (file)
@@ -46,6 +46,60 @@ struct nfc_rawsock {
 #define to_rawsock_sk(_tx_work) \
        ((struct sock *) container_of(_tx_work, struct nfc_rawsock, tx_work))
 
+#ifdef CONFIG_NFC_LLCP
+
+void nfc_llcp_mac_is_down(struct nfc_dev *dev);
+void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx,
+                       u8 comm_mode, u8 rf_mode);
+int nfc_llcp_register_device(struct nfc_dev *dev);
+void nfc_llcp_unregister_device(struct nfc_dev *dev);
+int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len);
+u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, u8 *general_bytes_len);
+int __init nfc_llcp_init(void);
+void nfc_llcp_exit(void);
+
+#else
+
+void nfc_llcp_mac_is_down(struct nfc_dev *dev)
+{
+}
+
+void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx,
+                       u8 comm_mode, u8 rf_mode)
+{
+}
+
+static inline int nfc_llcp_register_device(struct nfc_dev *dev)
+{
+       return 0;
+}
+
+static inline void nfc_llcp_unregister_device(struct nfc_dev *dev)
+{
+}
+
+static inline int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len)
+{
+       return 0;
+}
+
+static inline u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, u8 *gb_len)
+{
+       *gb_len = 0;
+       return NULL;
+}
+
+static inline int nfc_llcp_init(void)
+{
+       return 0;
+}
+
+static inline void nfc_llcp_exit(void)
+{
+}
+
+#endif
+
 int __init rawsock_init(void);
 void rawsock_exit(void);
 
@@ -68,6 +122,10 @@ int nfc_genl_targets_found(struct nfc_dev *dev);
 int nfc_genl_device_added(struct nfc_dev *dev);
 int nfc_genl_device_removed(struct nfc_dev *dev);
 
+int nfc_genl_dep_link_up_event(struct nfc_dev *dev, u32 target_idx,
+                              u8 comm_mode, u8 rf_mode);
+int nfc_genl_dep_link_down_event(struct nfc_dev *dev);
+
 struct nfc_dev *nfc_get_device(unsigned idx);
 
 static inline void nfc_put_device(struct nfc_dev *dev)
@@ -102,6 +160,11 @@ int nfc_start_poll(struct nfc_dev *dev, u32 protocols);
 
 int nfc_stop_poll(struct nfc_dev *dev);
 
+int nfc_dep_link_up(struct nfc_dev *dev, int target_idx,
+                               u8 comm_mode, u8 rf_mode);
+
+int nfc_dep_link_down(struct nfc_dev *dev);
+
 int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol);
 
 int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx);
index 68ecf3fa94e00ee293fe48c1bccfe9ba487bae62..2e2f8c6a61fe90579486c553032d14af2a7f0588 100644 (file)
@@ -21,7 +21,7 @@
  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__
 
 #include <net/tcp_states.h>
 #include <linux/nfc.h>
@@ -208,13 +208,10 @@ static int rawsock_sendmsg(struct kiocb *iocb, struct socket *sock,
        if (sock->state != SS_CONNECTED)
                return -ENOTCONN;
 
-       skb = sock_alloc_send_skb(sk, len + dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE,
-                                       msg->msg_flags & MSG_DONTWAIT, &rc);
-       if (!skb)
+       skb = nfc_alloc_send_skb(dev, sk, msg->msg_flags, len, &rc);
+       if (skb == NULL)
                return rc;
 
-       skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE);
-
        rc = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
        if (rc < 0) {
                kfree_skb(skb);
@@ -313,7 +310,7 @@ static int rawsock_create(struct net *net, struct socket *sock,
 
        sock->ops = &rawsock_ops;
 
-       sk = sk_alloc(net, PF_NFC, GFP_KERNEL, nfc_proto->proto);
+       sk = sk_alloc(net, PF_NFC, GFP_ATOMIC, nfc_proto->proto);
        if (!sk)
                return -ENOMEM;
 
index fb08c28fc90ad9b1051912c8cd878cbaaa6d6187..43ad9c81efcff1164b08c532e29f7a73e84d5cbf 100644 (file)
@@ -249,12 +249,11 @@ struct cfg80211_event {
                        u16 status;
                } cr;
                struct {
-                       struct ieee80211_channel *channel;
-                       u8 bssid[ETH_ALEN];
                        const u8 *req_ie;
                        const u8 *resp_ie;
                        size_t req_ie_len;
                        size_t resp_ie_len;
+                       struct cfg80211_bss *bss;
                } rm;
                struct {
                        const u8 *ie;
@@ -403,8 +402,7 @@ int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
                        struct net_device *dev, u16 reason,
                        bool wextev);
 void __cfg80211_roamed(struct wireless_dev *wdev,
-                      struct ieee80211_channel *channel,
-                      const u8 *bssid,
+                      struct cfg80211_bss *bss,
                       const u8 *req_ie, size_t req_ie_len,
                       const u8 *resp_ie, size_t resp_ie_len);
 int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
index ba439664c2e0d33428e008473e1fcf3c86b70247..b07c4fc4ae223363659592f91a9b6ff37ac42862 100644 (file)
@@ -47,22 +47,21 @@ static struct genl_family nl80211_fam = {
 };
 
 /* internal helper: get rdev and dev */
-static int get_rdev_dev_by_info_ifindex(struct genl_info *info,
-                                      struct cfg80211_registered_device **rdev,
-                                      struct net_device **dev)
+static int get_rdev_dev_by_ifindex(struct net *netns, struct nlattr **attrs,
+                                  struct cfg80211_registered_device **rdev,
+                                  struct net_device **dev)
 {
-       struct nlattr **attrs = info->attrs;
        int ifindex;
 
        if (!attrs[NL80211_ATTR_IFINDEX])
                return -EINVAL;
 
        ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]);
-       *dev = dev_get_by_index(genl_info_net(info), ifindex);
+       *dev = dev_get_by_index(netns, ifindex);
        if (!*dev)
                return -ENODEV;
 
-       *rdev = cfg80211_get_dev_from_ifindex(genl_info_net(info), ifindex);
+       *rdev = cfg80211_get_dev_from_ifindex(netns, ifindex);
        if (IS_ERR(*rdev)) {
                dev_put(*dev);
                return PTR_ERR(*rdev);
@@ -2247,6 +2246,7 @@ static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = {
        [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG },
        [NL80211_STA_FLAG_MFP] = { .type = NLA_FLAG },
        [NL80211_STA_FLAG_AUTHENTICATED] = { .type = NLA_FLAG },
+       [NL80211_STA_FLAG_TDLS_PEER] = { .type = NLA_FLAG },
 };
 
 static int parse_station_flags(struct genl_info *info,
@@ -2579,6 +2579,9 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
                params.ht_capa =
                        nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
 
+       if (!rdev->ops->change_station)
+               return -EOPNOTSUPP;
+
        if (parse_station_flags(info, &params))
                return -EINVAL;
 
@@ -2590,73 +2593,84 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
                params.plink_state =
                    nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]);
 
-       params.vlan = get_vlan(info, rdev);
-       if (IS_ERR(params.vlan))
-               return PTR_ERR(params.vlan);
-
-       /* validate settings */
-       err = 0;
-
        switch (dev->ieee80211_ptr->iftype) {
        case NL80211_IFTYPE_AP:
        case NL80211_IFTYPE_AP_VLAN:
        case NL80211_IFTYPE_P2P_GO:
                /* disallow mesh-specific things */
                if (params.plink_action)
-                       err = -EINVAL;
+                       return -EINVAL;
+
+               /* TDLS can't be set, ... */
+               if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
+                       return -EINVAL;
+               /*
+                * ... but don't bother the driver with it. This works around
+                * a hostapd/wpa_supplicant issue -- it always includes the
+                * TLDS_PEER flag in the mask even for AP mode.
+                */
+               params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
+
+               /* accept only the listed bits */
+               if (params.sta_flags_mask &
+                               ~(BIT(NL80211_STA_FLAG_AUTHORIZED) |
+                                 BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
+                                 BIT(NL80211_STA_FLAG_WME) |
+                                 BIT(NL80211_STA_FLAG_MFP)))
+                       return -EINVAL;
+
+               /* must be last in here for error handling */
+               params.vlan = get_vlan(info, rdev);
+               if (IS_ERR(params.vlan))
+                       return PTR_ERR(params.vlan);
                break;
        case NL80211_IFTYPE_P2P_CLIENT:
        case NL80211_IFTYPE_STATION:
                /* disallow things sta doesn't support */
                if (params.plink_action)
-                       err = -EINVAL;
-               if (params.vlan)
-                       err = -EINVAL;
-               if (params.supported_rates &&
-                   !(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
-                       err = -EINVAL;
+                       return -EINVAL;
                if (params.ht_capa)
-                       err = -EINVAL;
+                       return -EINVAL;
                if (params.listen_interval >= 0)
-                       err = -EINVAL;
-               if (params.sta_flags_mask &
-                               ~(BIT(NL80211_STA_FLAG_AUTHORIZED) |
-                                 BIT(NL80211_STA_FLAG_TDLS_PEER)))
-                       err = -EINVAL;
-               /* can't change the TDLS bit */
-               if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) &&
-                   (params.sta_flags_mask & BIT(NL80211_STA_FLAG_TDLS_PEER)))
-                       err = -EINVAL;
+                       return -EINVAL;
+               /*
+                * Don't allow userspace to change the TDLS_PEER flag,
+                * but silently ignore attempts to change it since we
+                * don't have state here to verify that it doesn't try
+                * to change the flag.
+                */
+               params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
+
+               /* reject any changes other than AUTHORIZED */
+               if (params.sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED))
+                       return -EINVAL;
                break;
        case NL80211_IFTYPE_MESH_POINT:
                /* disallow things mesh doesn't support */
                if (params.vlan)
-                       err = -EINVAL;
+                       return -EINVAL;
                if (params.ht_capa)
-                       err = -EINVAL;
+                       return -EINVAL;
                if (params.listen_interval >= 0)
-                       err = -EINVAL;
+                       return -EINVAL;
+               /*
+                * No special handling for TDLS here -- the userspace
+                * mesh code doesn't have this bug.
+                */
                if (params.sta_flags_mask &
                                ~(BIT(NL80211_STA_FLAG_AUTHENTICATED) |
                                  BIT(NL80211_STA_FLAG_MFP) |
                                  BIT(NL80211_STA_FLAG_AUTHORIZED)))
-                       err = -EINVAL;
+                       return -EINVAL;
                break;
        default:
-               err = -EINVAL;
+               return -EOPNOTSUPP;
        }
 
-       if (err)
-               goto out;
-
-       if (!rdev->ops->change_station) {
-               err = -EOPNOTSUPP;
-               goto out;
-       }
+       /* be aware of params.vlan when changing code here */
 
        err = rdev->ops->change_station(&rdev->wiphy, dev, mac_addr, &params);
 
- out:
        if (params.vlan)
                dev_put(params.vlan);
 
@@ -2711,70 +2725,81 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
                params.plink_action =
                    nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
 
+       if (!rdev->ops->add_station)
+               return -EOPNOTSUPP;
+
        if (parse_station_flags(info, &params))
                return -EINVAL;
 
-       /* parse WME attributes if sta is WME capable */
-       if ((rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) &&
-           (params.sta_flags_set & BIT(NL80211_STA_FLAG_WME)) &&
-           info->attrs[NL80211_ATTR_STA_WME]) {
-               struct nlattr *tb[NL80211_STA_WME_MAX + 1];
-               struct nlattr *nla;
+       switch (dev->ieee80211_ptr->iftype) {
+       case NL80211_IFTYPE_AP:
+       case NL80211_IFTYPE_AP_VLAN:
+       case NL80211_IFTYPE_P2P_GO:
+               /* parse WME attributes if sta is WME capable */
+               if ((rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) &&
+                   (params.sta_flags_set & BIT(NL80211_STA_FLAG_WME)) &&
+                   info->attrs[NL80211_ATTR_STA_WME]) {
+                       struct nlattr *tb[NL80211_STA_WME_MAX + 1];
+                       struct nlattr *nla;
+
+                       nla = info->attrs[NL80211_ATTR_STA_WME];
+                       err = nla_parse_nested(tb, NL80211_STA_WME_MAX, nla,
+                                              nl80211_sta_wme_policy);
+                       if (err)
+                               return err;
 
-               nla = info->attrs[NL80211_ATTR_STA_WME];
-               err = nla_parse_nested(tb, NL80211_STA_WME_MAX, nla,
-                                      nl80211_sta_wme_policy);
-               if (err)
-                       return err;
+                       if (tb[NL80211_STA_WME_UAPSD_QUEUES])
+                               params.uapsd_queues =
+                                    nla_get_u8(tb[NL80211_STA_WME_UAPSD_QUEUES]);
+                       if (params.uapsd_queues &
+                                       ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK)
+                               return -EINVAL;
 
-               if (tb[NL80211_STA_WME_UAPSD_QUEUES])
-                       params.uapsd_queues =
-                            nla_get_u8(tb[NL80211_STA_WME_UAPSD_QUEUES]);
-               if (params.uapsd_queues & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK)
-                       return -EINVAL;
+                       if (tb[NL80211_STA_WME_MAX_SP])
+                               params.max_sp =
+                                    nla_get_u8(tb[NL80211_STA_WME_MAX_SP]);
 
-               if (tb[NL80211_STA_WME_MAX_SP])
-                       params.max_sp =
-                            nla_get_u8(tb[NL80211_STA_WME_MAX_SP]);
+                       if (params.max_sp &
+                                       ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK)
+                               return -EINVAL;
 
-               if (params.max_sp & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK)
+                       params.sta_modify_mask |= STATION_PARAM_APPLY_UAPSD;
+               }
+               /* TDLS peers cannot be added */
+               if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
                        return -EINVAL;
+               /* but don't bother the driver with it */
+               params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
 
-               params.sta_modify_mask |= STATION_PARAM_APPLY_UAPSD;
+               /* must be last in here for error handling */
+               params.vlan = get_vlan(info, rdev);
+               if (IS_ERR(params.vlan))
+                       return PTR_ERR(params.vlan);
+               break;
+       case NL80211_IFTYPE_MESH_POINT:
+               /* TDLS peers cannot be added */
+               if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
+                       return -EINVAL;
+               break;
+       case NL80211_IFTYPE_STATION:
+               /* Only TDLS peers can be added */
+               if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
+                       return -EINVAL;
+               /* Can only add if TDLS ... */
+               if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS))
+                       return -EOPNOTSUPP;
+               /* ... with external setup is supported */
+               if (!(rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP))
+                       return -EOPNOTSUPP;
+               break;
+       default:
+               return -EOPNOTSUPP;
        }
 
-       if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
-           dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
-           dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT &&
-           dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO &&
-           dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION)
-               return -EINVAL;
-
-       /*
-        * Only managed stations can add TDLS peers, and only when the
-        * wiphy supports external TDLS setup.
-        */
-       if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION &&
-           !((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) &&
-             (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) &&
-             (rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP)))
-               return -EINVAL;
-
-       params.vlan = get_vlan(info, rdev);
-       if (IS_ERR(params.vlan))
-               return PTR_ERR(params.vlan);
-
-       /* validate settings */
-       err = 0;
-
-       if (!rdev->ops->add_station) {
-               err = -EOPNOTSUPP;
-               goto out;
-       }
+       /* be aware of params.vlan when changing code here */
 
        err = rdev->ops->add_station(&rdev->wiphy, dev, mac_addr, &params);
 
- out:
        if (params.vlan)
                dev_put(params.vlan);
        return err;
@@ -4795,7 +4820,7 @@ static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
 static int nl80211_testmode_dump(struct sk_buff *skb,
                                 struct netlink_callback *cb)
 {
-       struct cfg80211_registered_device *dev;
+       struct cfg80211_registered_device *rdev;
        int err;
        long phy_idx;
        void *data = NULL;
@@ -4813,9 +4838,21 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
                                  nl80211_policy);
                if (err)
                        return err;
-               if (!nl80211_fam.attrbuf[NL80211_ATTR_WIPHY])
-                       return -EINVAL;
-               phy_idx = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_WIPHY]);
+               if (nl80211_fam.attrbuf[NL80211_ATTR_WIPHY]) {
+                       phy_idx = nla_get_u32(
+                               nl80211_fam.attrbuf[NL80211_ATTR_WIPHY]);
+               } else {
+                       struct net_device *netdev;
+
+                       err = get_rdev_dev_by_ifindex(sock_net(skb->sk),
+                                                     nl80211_fam.attrbuf,
+                                                     &rdev, &netdev);
+                       if (err)
+                               return err;
+                       dev_put(netdev);
+                       phy_idx = rdev->wiphy_idx;
+                       cfg80211_unlock_rdev(rdev);
+               }
                if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA])
                        cb->args[1] =
                                (long)nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA];
@@ -4827,15 +4864,15 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
        }
 
        mutex_lock(&cfg80211_mutex);
-       dev = cfg80211_rdev_by_wiphy_idx(phy_idx);
-       if (!dev) {
+       rdev = cfg80211_rdev_by_wiphy_idx(phy_idx);
+       if (!rdev) {
                mutex_unlock(&cfg80211_mutex);
                return -ENOENT;
        }
-       cfg80211_lock_rdev(dev);
+       cfg80211_lock_rdev(rdev);
        mutex_unlock(&cfg80211_mutex);
 
-       if (!dev->ops->testmode_dump) {
+       if (!rdev->ops->testmode_dump) {
                err = -EOPNOTSUPP;
                goto out_err;
        }
@@ -4846,7 +4883,7 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
                                           NL80211_CMD_TESTMODE);
                struct nlattr *tmdata;
 
-               if (nla_put_u32(skb, NL80211_ATTR_WIPHY, dev->wiphy_idx) < 0) {
+               if (nla_put_u32(skb, NL80211_ATTR_WIPHY, phy_idx) < 0) {
                        genlmsg_cancel(skb, hdr);
                        break;
                }
@@ -4856,8 +4893,8 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
                        genlmsg_cancel(skb, hdr);
                        break;
                }
-               err = dev->ops->testmode_dump(&dev->wiphy, skb, cb,
-                                             data, data_len);
+               err = rdev->ops->testmode_dump(&rdev->wiphy, skb, cb,
+                                              data, data_len);
                nla_nest_end(skb, tmdata);
 
                if (err == -ENOBUFS || err == -ENOENT) {
@@ -4875,7 +4912,7 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
        /* see above */
        cb->args[0] = phy_idx + 1;
  out_err:
-       cfg80211_unlock_rdev(dev);
+       cfg80211_unlock_rdev(rdev);
        return err;
 }
 
@@ -6110,7 +6147,8 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
                }
                info->user_ptr[0] = rdev;
        } else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) {
-               err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
+               err = get_rdev_dev_by_ifindex(genl_info_net(info), info->attrs,
+                                             &rdev, &dev);
                if (err) {
                        if (rtnl)
                                rtnl_unlock();
index 70b171a52aeacdb686ac3a6a79c4997b85b0ec19..c45c8b772dddec9c731a9d60c47eaa6318cc7f4e 100644 (file)
@@ -873,10 +873,22 @@ static void handle_channel(struct wiphy *wiphy,
        chan->flags = flags | bw_flags | map_regdom_flags(reg_rule->flags);
        chan->max_antenna_gain = min(chan->orig_mag,
                (int) MBI_TO_DBI(power_rule->max_antenna_gain));
-       if (chan->orig_mpwr)
-               chan->max_power = min(chan->orig_mpwr,
-                       (int) MBM_TO_DBM(power_rule->max_eirp));
-       else
+       if (chan->orig_mpwr) {
+               /*
+                * Devices that have their own custom regulatory domain
+                * but also use WIPHY_FLAG_STRICT_REGULATORY will follow the
+                * passed country IE power settings.
+                */
+               if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE &&
+                   wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY &&
+                   wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) {
+                       chan->max_power =
+                               MBM_TO_DBM(power_rule->max_eirp);
+               } else {
+                       chan->max_power = min(chan->orig_mpwr,
+                               (int) MBM_TO_DBM(power_rule->max_eirp));
+               }
+       } else
                chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp);
 }
 
@@ -1163,9 +1175,21 @@ void regulatory_update(struct wiphy *wiphy,
 static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator)
 {
        struct cfg80211_registered_device *rdev;
+       struct wiphy *wiphy;
 
-       list_for_each_entry(rdev, &cfg80211_rdev_list, list)
-               wiphy_update_regulatory(&rdev->wiphy, initiator);
+       list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
+               wiphy = &rdev->wiphy;
+               wiphy_update_regulatory(wiphy, initiator);
+               /*
+                * Regulatory updates set by CORE are ignored for custom
+                * regulatory cards. Let us notify the changes to the driver,
+                * as some drivers used this to restore its orig_* reg domain.
+                */
+               if (initiator == NL80211_REGDOM_SET_BY_CORE &&
+                   wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY &&
+                   wiphy->reg_notifier)
+                       wiphy->reg_notifier(wiphy, last_request);
+       }
 }
 
 static void handle_channel_custom(struct wiphy *wiphy,
@@ -1768,6 +1792,26 @@ static void restore_alpha2(char *alpha2, bool reset_user)
                REG_DBG_PRINT("Restoring regulatory settings\n");
 }
 
+static void restore_custom_reg_settings(struct wiphy *wiphy)
+{
+       struct ieee80211_supported_band *sband;
+       enum ieee80211_band band;
+       struct ieee80211_channel *chan;
+       int i;
+
+       for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+               sband = wiphy->bands[band];
+               if (!sband)
+                       continue;
+               for (i = 0; i < sband->n_channels; i++) {
+                       chan = &sband->channels[i];
+                       chan->flags = chan->orig_flags;
+                       chan->max_antenna_gain = chan->orig_mag;
+                       chan->max_power = chan->orig_mpwr;
+               }
+       }
+}
+
 /*
  * Restoring regulatory settings involves ingoring any
  * possibly stale country IE information and user regulatory
@@ -1789,6 +1833,7 @@ static void restore_regulatory_settings(bool reset_user)
        struct reg_beacon *reg_beacon, *btmp;
        struct regulatory_request *reg_request, *tmp;
        LIST_HEAD(tmp_reg_req_list);
+       struct cfg80211_registered_device *rdev;
 
        mutex_lock(&cfg80211_mutex);
        mutex_lock(&reg_mutex);
@@ -1837,6 +1882,11 @@ static void restore_regulatory_settings(bool reset_user)
        /* First restore to the basic regulatory settings */
        cfg80211_regdomain = cfg80211_world_regdom;
 
+       list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
+               if (rdev->wiphy.flags & WIPHY_FLAG_CUSTOM_REGULATORY)
+                       restore_custom_reg_settings(&rdev->wiphy);
+       }
+
        mutex_unlock(&reg_mutex);
        mutex_unlock(&cfg80211_mutex);
 
index f0c900ce2fb9ee2dd0606fa651c15b078eb497e0..7b9ecaed96bef13aab274b5cd3686dd2487096ac 100644 (file)
@@ -553,45 +553,35 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
 EXPORT_SYMBOL(cfg80211_connect_result);
 
 void __cfg80211_roamed(struct wireless_dev *wdev,
-                      struct ieee80211_channel *channel,
-                      const u8 *bssid,
+                      struct cfg80211_bss *bss,
                       const u8 *req_ie, size_t req_ie_len,
                       const u8 *resp_ie, size_t resp_ie_len)
 {
-       struct cfg80211_bss *bss;
 #ifdef CONFIG_CFG80211_WEXT
        union iwreq_data wrqu;
 #endif
-
        ASSERT_WDEV_LOCK(wdev);
 
        if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION &&
                    wdev->iftype != NL80211_IFTYPE_P2P_CLIENT))
-               return;
+               goto out;
 
        if (wdev->sme_state != CFG80211_SME_CONNECTED)
-               return;
+               goto out;
 
        /* internal error -- how did we get to CONNECTED w/o BSS? */
        if (WARN_ON(!wdev->current_bss)) {
-               return;
+               goto out;
        }
 
        cfg80211_unhold_bss(wdev->current_bss);
        cfg80211_put_bss(&wdev->current_bss->pub);
        wdev->current_bss = NULL;
 
-       bss = cfg80211_get_bss(wdev->wiphy, channel, bssid,
-                              wdev->ssid, wdev->ssid_len,
-                              WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
-
-       if (WARN_ON(!bss))
-               return;
-
        cfg80211_hold_bss(bss_from_pub(bss));
        wdev->current_bss = bss_from_pub(bss);
 
-       nl80211_send_roamed(wiphy_to_dev(wdev->wiphy), wdev->netdev, bssid,
+       nl80211_send_roamed(wiphy_to_dev(wdev->wiphy), wdev->netdev, bss->bssid,
                            req_ie, req_ie_len, resp_ie, resp_ie_len,
                            GFP_KERNEL);
 
@@ -612,11 +602,15 @@ void __cfg80211_roamed(struct wireless_dev *wdev,
 
        memset(&wrqu, 0, sizeof(wrqu));
        wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-       memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
-       memcpy(wdev->wext.prev_bssid, bssid, ETH_ALEN);
+       memcpy(wrqu.ap_addr.sa_data, bss->bssid, ETH_ALEN);
+       memcpy(wdev->wext.prev_bssid, bss->bssid, ETH_ALEN);
        wdev->wext.prev_bssid_valid = true;
        wireless_send_event(wdev->netdev, SIOCGIWAP, &wrqu, NULL);
 #endif
+
+       return;
+out:
+       cfg80211_put_bss(bss);
 }
 
 void cfg80211_roamed(struct net_device *dev,
@@ -624,6 +618,27 @@ void cfg80211_roamed(struct net_device *dev,
                     const u8 *bssid,
                     const u8 *req_ie, size_t req_ie_len,
                     const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp)
+{
+       struct wireless_dev *wdev = dev->ieee80211_ptr;
+       struct cfg80211_bss *bss;
+
+       CFG80211_DEV_WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTED);
+
+       bss = cfg80211_get_bss(wdev->wiphy, channel, bssid, wdev->ssid,
+                              wdev->ssid_len, WLAN_CAPABILITY_ESS,
+                              WLAN_CAPABILITY_ESS);
+       if (WARN_ON(!bss))
+               return;
+
+       cfg80211_roamed_bss(dev, bss, req_ie, req_ie_len, resp_ie,
+                           resp_ie_len, gfp);
+}
+EXPORT_SYMBOL(cfg80211_roamed);
+
+void cfg80211_roamed_bss(struct net_device *dev,
+                        struct cfg80211_bss *bss, const u8 *req_ie,
+                        size_t req_ie_len, const u8 *resp_ie,
+                        size_t resp_ie_len, gfp_t gfp)
 {
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
@@ -632,26 +647,30 @@ void cfg80211_roamed(struct net_device *dev,
 
        CFG80211_DEV_WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTED);
 
+       if (WARN_ON(!bss))
+               return;
+
        ev = kzalloc(sizeof(*ev) + req_ie_len + resp_ie_len, gfp);
-       if (!ev)
+       if (!ev) {
+               cfg80211_put_bss(bss);
                return;
+       }
 
        ev->type = EVENT_ROAMED;
-       ev->rm.channel = channel;
-       memcpy(ev->rm.bssid, bssid, ETH_ALEN);
        ev->rm.req_ie = ((u8 *)ev) + sizeof(*ev);
        ev->rm.req_ie_len = req_ie_len;
        memcpy((void *)ev->rm.req_ie, req_ie, req_ie_len);
        ev->rm.resp_ie = ((u8 *)ev) + sizeof(*ev) + req_ie_len;
        ev->rm.resp_ie_len = resp_ie_len;
        memcpy((void *)ev->rm.resp_ie, resp_ie, resp_ie_len);
+       ev->rm.bss = bss;
 
        spin_lock_irqsave(&wdev->event_lock, flags);
        list_add_tail(&ev->list, &wdev->event_list);
        spin_unlock_irqrestore(&wdev->event_lock, flags);
        queue_work(cfg80211_wq, &rdev->event_work);
 }
-EXPORT_SYMBOL(cfg80211_roamed);
+EXPORT_SYMBOL(cfg80211_roamed_bss);
 
 void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
                             size_t ie_len, u16 reason, bool from_ap)
index 9c601d59b77a802664c763c8cbaa02936348fc64..e77df75850048c3e5b4eb19f788581f7226c0c34 100644 (file)
@@ -740,9 +740,9 @@ static void cfg80211_process_wdev_events(struct wireless_dev *wdev)
                                NULL);
                        break;
                case EVENT_ROAMED:
-                       __cfg80211_roamed(wdev, ev->rm.channel, ev->rm.bssid,
-                                         ev->rm.req_ie, ev->rm.req_ie_len,
-                                         ev->rm.resp_ie, ev->rm.resp_ie_len);
+                       __cfg80211_roamed(wdev, ev->rm.bss, ev->rm.req_ie,
+                                         ev->rm.req_ie_len, ev->rm.resp_ie,
+                                         ev->rm.resp_ie_len);
                        break;
                case EVENT_DISCONNECTED:
                        __cfg80211_disconnected(wdev->netdev,
This page took 0.818077 seconds and 5 git commands to generate.