new file mode 100644
@@ -0,0 +1,123141 @@
+From 748eb185cad62c456dcd316c941f9835520a946d Mon Sep 17 00:00:00 2001
+From: John Weber <rjohnweber@gmail.com>
+Date: Sat, 9 Mar 2013 09:23:58 -0600
+Subject: [meta-fsl-arm-extra][PATCH 1/2] linux-imx (3.0.35): remove brcm80211
+ staging driver
+
+Upstream-Status: Pending
+
+Signed-off-by: John Weber <rjohnweber@gmail.com>
+---
+ drivers/staging/Kconfig | 2 -
+ drivers/staging/Makefile | 2 -
+ drivers/staging/brcm80211/Kconfig | 40 -
+ drivers/staging/brcm80211/Makefile | 24 -
+ drivers/staging/brcm80211/README | 64 -
+ drivers/staging/brcm80211/TODO | 15 -
+ drivers/staging/brcm80211/brcmfmac/Makefile | 56 -
+ drivers/staging/brcm80211/brcmfmac/README | 2 -
+ drivers/staging/brcm80211/brcmfmac/aiutils.c | 1 -
+ drivers/staging/brcm80211/brcmfmac/bcmcdc.h | 98 -
+ drivers/staging/brcm80211/brcmfmac/bcmchip.h | 35 -
+ drivers/staging/brcm80211/brcmfmac/bcmsdbus.h | 113 -
+ drivers/staging/brcm80211/brcmfmac/bcmsdh.c | 631 -
+ drivers/staging/brcm80211/brcmfmac/bcmsdh_linux.c | 386 -
+ drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c | 1239 -
+ drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.h | 134 -
+ .../brcm80211/brcmfmac/bcmsdh_sdmmc_linux.c | 235 -
+ drivers/staging/brcm80211/brcmfmac/dhd.h | 414 -
+ drivers/staging/brcm80211/brcmfmac/dhd_bus.h | 82 -
+ drivers/staging/brcm80211/brcmfmac/dhd_cdc.c | 474 -
+ drivers/staging/brcm80211/brcmfmac/dhd_common.c | 1848 --
+ .../staging/brcm80211/brcmfmac/dhd_custom_gpio.c | 158 -
+ drivers/staging/brcm80211/brcmfmac/dhd_dbg.h | 103 -
+ drivers/staging/brcm80211/brcmfmac/dhd_linux.c | 2862 --
+ .../staging/brcm80211/brcmfmac/dhd_linux_sched.c | 25 -
+ drivers/staging/brcm80211/brcmfmac/dhd_proto.h | 90 -
+ drivers/staging/brcm80211/brcmfmac/dhd_sdio.c | 6390 -----
+ drivers/staging/brcm80211/brcmfmac/dhdioctl.h | 100 -
+ drivers/staging/brcm80211/brcmfmac/dngl_stats.h | 32 -
+ .../staging/brcm80211/brcmfmac/hndrte_armtrap.h | 75 -
+ drivers/staging/brcm80211/brcmfmac/hndrte_cons.h | 62 -
+ drivers/staging/brcm80211/brcmfmac/msgtrace.h | 61 -
+ drivers/staging/brcm80211/brcmfmac/sdioh.h | 63 -
+ drivers/staging/brcm80211/brcmfmac/sdiovar.h | 38 -
+ drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c | 4428 ---
+ drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h | 414 -
+ drivers/staging/brcm80211/brcmfmac/wl_iw.c | 3693 ---
+ drivers/staging/brcm80211/brcmfmac/wl_iw.h | 142 -
+ drivers/staging/brcm80211/brcmsmac/Makefile | 59 -
+ drivers/staging/brcm80211/brcmsmac/aiutils.c | 2054 --
+ drivers/staging/brcm80211/brcmsmac/aiutils.h | 546 -
+ drivers/staging/brcm80211/brcmsmac/bcmotp.c | 936 -
+ drivers/staging/brcm80211/brcmsmac/bcmsrom.c | 714 -
+ drivers/staging/brcm80211/brcmsmac/bcmsrom_tbl.h | 513 -
+ drivers/staging/brcm80211/brcmsmac/d11.h | 1773 --
+ drivers/staging/brcm80211/brcmsmac/hnddma.c | 1756 --
+ drivers/staging/brcm80211/brcmsmac/nicpci.c | 836 -
+ drivers/staging/brcm80211/brcmsmac/nvram.c | 215 -
+ .../staging/brcm80211/brcmsmac/phy/phy_version.h | 36 -
+ .../staging/brcm80211/brcmsmac/phy/wlc_phy_cmn.c | 3307 ---
+ .../staging/brcm80211/brcmsmac/phy/wlc_phy_hal.h | 256 -
+ .../staging/brcm80211/brcmsmac/phy/wlc_phy_int.h | 1226 -
+ .../staging/brcm80211/brcmsmac/phy/wlc_phy_lcn.c | 5302 ----
+ .../staging/brcm80211/brcmsmac/phy/wlc_phy_lcn.h | 119 -
+ drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_n.c |29169 --------------------
+ .../staging/brcm80211/brcmsmac/phy/wlc_phy_qmath.c | 296 -
+ .../staging/brcm80211/brcmsmac/phy/wlc_phy_qmath.h | 40 -
+ .../staging/brcm80211/brcmsmac/phy/wlc_phy_radio.h | 1533 -
+ .../staging/brcm80211/brcmsmac/phy/wlc_phyreg_n.h | 167 -
+ .../brcm80211/brcmsmac/phy/wlc_phytbl_lcn.c | 3639 ---
+ .../brcm80211/brcmsmac/phy/wlc_phytbl_lcn.h | 49 -
+ .../staging/brcm80211/brcmsmac/phy/wlc_phytbl_n.c |10632 -------
+ .../staging/brcm80211/brcmsmac/phy/wlc_phytbl_n.h | 39 -
+ drivers/staging/brcm80211/brcmsmac/wl_dbg.h | 92 -
+ drivers/staging/brcm80211/brcmsmac/wl_export.h | 47 -
+ drivers/staging/brcm80211/brcmsmac/wl_mac80211.c | 1942 --
+ drivers/staging/brcm80211/brcmsmac/wl_mac80211.h | 85 -
+ drivers/staging/brcm80211/brcmsmac/wl_ucode.h | 49 -
+ .../staging/brcm80211/brcmsmac/wl_ucode_loader.c | 111 -
+ drivers/staging/brcm80211/brcmsmac/wlc_alloc.c | 300 -
+ drivers/staging/brcm80211/brcmsmac/wlc_alloc.h | 18 -
+ drivers/staging/brcm80211/brcmsmac/wlc_ampdu.c | 1253 -
+ drivers/staging/brcm80211/brcmsmac/wlc_ampdu.h | 29 -
+ drivers/staging/brcm80211/brcmsmac/wlc_antsel.c | 320 -
+ drivers/staging/brcm80211/brcmsmac/wlc_antsel.h | 29 -
+ drivers/staging/brcm80211/brcmsmac/wlc_bmac.c | 3602 ---
+ drivers/staging/brcm80211/brcmsmac/wlc_bmac.h | 179 -
+ drivers/staging/brcm80211/brcmsmac/wlc_bsscfg.h | 135 -
+ drivers/staging/brcm80211/brcmsmac/wlc_cfg.h | 280 -
+ drivers/staging/brcm80211/brcmsmac/wlc_channel.c | 1557 --
+ drivers/staging/brcm80211/brcmsmac/wlc_channel.h | 120 -
+ drivers/staging/brcm80211/brcmsmac/wlc_key.h | 140 -
+ drivers/staging/brcm80211/brcmsmac/wlc_main.c | 7537 -----
+ drivers/staging/brcm80211/brcmsmac/wlc_main.h | 939 -
+ drivers/staging/brcm80211/brcmsmac/wlc_phy_shim.c | 243 -
+ drivers/staging/brcm80211/brcmsmac/wlc_phy_shim.h | 112 -
+ drivers/staging/brcm80211/brcmsmac/wlc_pmu.c | 1929 --
+ drivers/staging/brcm80211/brcmsmac/wlc_pmu.h | 58 -
+ drivers/staging/brcm80211/brcmsmac/wlc_pub.h | 584 -
+ drivers/staging/brcm80211/brcmsmac/wlc_rate.c | 499 -
+ drivers/staging/brcm80211/brcmsmac/wlc_rate.h | 169 -
+ drivers/staging/brcm80211/brcmsmac/wlc_scb.h | 80 -
+ drivers/staging/brcm80211/brcmsmac/wlc_stf.c | 523 -
+ drivers/staging/brcm80211/brcmsmac/wlc_stf.h | 38 -
+ drivers/staging/brcm80211/brcmsmac/wlc_types.h | 37 -
+ drivers/staging/brcm80211/include/aidmp.h | 374 -
+ drivers/staging/brcm80211/include/bcmdefs.h | 150 -
+ drivers/staging/brcm80211/include/bcmdevs.h | 124 -
+ drivers/staging/brcm80211/include/bcmnvram.h | 153 -
+ drivers/staging/brcm80211/include/bcmotp.h | 44 -
+ drivers/staging/brcm80211/include/bcmsdh.h | 205 -
+ drivers/staging/brcm80211/include/bcmsdpcm.h | 208 -
+ drivers/staging/brcm80211/include/bcmsrom.h | 34 -
+ drivers/staging/brcm80211/include/bcmsrom_fmt.h | 367 -
+ drivers/staging/brcm80211/include/bcmutils.h | 500 -
+ drivers/staging/brcm80211/include/bcmwifi.h | 167 -
+ drivers/staging/brcm80211/include/hnddma.h | 226 -
+ drivers/staging/brcm80211/include/hndsoc.h | 199 -
+ drivers/staging/brcm80211/include/nicpci.h | 79 -
+ drivers/staging/brcm80211/include/pci_core.h | 122 -
+ drivers/staging/brcm80211/include/pcicfg.h | 50 -
+ drivers/staging/brcm80211/include/pcie_core.h | 299 -
+ drivers/staging/brcm80211/include/proto/802.11.h | 200 -
+ drivers/staging/brcm80211/include/proto/bcmeth.h | 44 -
+ drivers/staging/brcm80211/include/proto/bcmevent.h | 207 -
+ drivers/staging/brcm80211/include/sbchipc.h | 1588 --
+ drivers/staging/brcm80211/include/sbconfig.h | 272 -
+ drivers/staging/brcm80211/include/sbhnddma.h | 315 -
+ drivers/staging/brcm80211/include/sbsdio.h | 152 -
+ drivers/staging/brcm80211/include/sbsdpcmdev.h | 281 -
+ drivers/staging/brcm80211/include/sdio.h | 552 -
+ drivers/staging/brcm80211/include/wlioctl.h | 1365 -
+ drivers/staging/brcm80211/util/Makefile | 29 -
+ drivers/staging/brcm80211/util/bcmutils.c | 796 -
+ drivers/staging/brcm80211/util/bcmwifi.c | 137 -
+ 125 files changed, 122118 deletions(-)
+ delete mode 100644 drivers/staging/brcm80211/Kconfig
+ delete mode 100644 drivers/staging/brcm80211/Makefile
+ delete mode 100644 drivers/staging/brcm80211/README
+ delete mode 100644 drivers/staging/brcm80211/TODO
+ delete mode 100644 drivers/staging/brcm80211/brcmfmac/Makefile
+ delete mode 100644 drivers/staging/brcm80211/brcmfmac/README
+ delete mode 100644 drivers/staging/brcm80211/brcmfmac/aiutils.c
+ delete mode 100644 drivers/staging/brcm80211/brcmfmac/bcmcdc.h
+ delete mode 100644 drivers/staging/brcm80211/brcmfmac/bcmchip.h
+ delete mode 100644 drivers/staging/brcm80211/brcmfmac/bcmsdbus.h
+ delete mode 100644 drivers/staging/brcm80211/brcmfmac/bcmsdh.c
+ delete mode 100644 drivers/staging/brcm80211/brcmfmac/bcmsdh_linux.c
+ delete mode 100644 drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c
+ delete mode 100644 drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.h
+ delete mode 100644 drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc_linux.c
+ delete mode 100644 drivers/staging/brcm80211/brcmfmac/dhd.h
+ delete mode 100644 drivers/staging/brcm80211/brcmfmac/dhd_bus.h
+ delete mode 100644 drivers/staging/brcm80211/brcmfmac/dhd_cdc.c
+ delete mode 100644 drivers/staging/brcm80211/brcmfmac/dhd_common.c
+ delete mode 100644 drivers/staging/brcm80211/brcmfmac/dhd_custom_gpio.c
+ delete mode 100644 drivers/staging/brcm80211/brcmfmac/dhd_dbg.h
+ delete mode 100644 drivers/staging/brcm80211/brcmfmac/dhd_linux.c
+ delete mode 100644 drivers/staging/brcm80211/brcmfmac/dhd_linux_sched.c
+ delete mode 100644 drivers/staging/brcm80211/brcmfmac/dhd_proto.h
+ delete mode 100644 drivers/staging/brcm80211/brcmfmac/dhd_sdio.c
+ delete mode 100644 drivers/staging/brcm80211/brcmfmac/dhdioctl.h
+ delete mode 100644 drivers/staging/brcm80211/brcmfmac/dngl_stats.h
+ delete mode 100644 drivers/staging/brcm80211/brcmfmac/hndrte_armtrap.h
+ delete mode 100644 drivers/staging/brcm80211/brcmfmac/hndrte_cons.h
+ delete mode 100644 drivers/staging/brcm80211/brcmfmac/msgtrace.h
+ delete mode 100644 drivers/staging/brcm80211/brcmfmac/sdioh.h
+ delete mode 100644 drivers/staging/brcm80211/brcmfmac/sdiovar.h
+ delete mode 100644 drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
+ delete mode 100644 drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h
+ delete mode 100644 drivers/staging/brcm80211/brcmfmac/wl_iw.c
+ delete mode 100644 drivers/staging/brcm80211/brcmfmac/wl_iw.h
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/Makefile
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/aiutils.c
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/aiutils.h
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/bcmotp.c
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/bcmsrom.c
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/bcmsrom_tbl.h
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/d11.h
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/hnddma.c
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/nicpci.c
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/nvram.c
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/phy/phy_version.h
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_cmn.c
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_hal.h
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_int.h
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_lcn.c
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_lcn.h
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_n.c
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_qmath.c
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_qmath.h
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_radio.h
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/phy/wlc_phyreg_n.h
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/phy/wlc_phytbl_lcn.c
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/phy/wlc_phytbl_lcn.h
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/phy/wlc_phytbl_n.c
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/phy/wlc_phytbl_n.h
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/wl_dbg.h
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/wl_export.h
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/wl_mac80211.c
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/wl_mac80211.h
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/wl_ucode.h
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/wl_ucode_loader.c
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/wlc_alloc.c
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/wlc_alloc.h
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/wlc_ampdu.c
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/wlc_ampdu.h
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/wlc_antsel.c
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/wlc_antsel.h
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/wlc_bmac.c
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/wlc_bmac.h
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/wlc_bsscfg.h
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/wlc_cfg.h
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/wlc_channel.c
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/wlc_channel.h
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/wlc_key.h
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/wlc_main.c
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/wlc_main.h
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/wlc_phy_shim.c
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/wlc_phy_shim.h
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/wlc_pmu.c
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/wlc_pmu.h
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/wlc_pub.h
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/wlc_rate.c
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/wlc_rate.h
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/wlc_scb.h
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/wlc_stf.c
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/wlc_stf.h
+ delete mode 100644 drivers/staging/brcm80211/brcmsmac/wlc_types.h
+ delete mode 100644 drivers/staging/brcm80211/include/aidmp.h
+ delete mode 100644 drivers/staging/brcm80211/include/bcmdefs.h
+ delete mode 100644 drivers/staging/brcm80211/include/bcmdevs.h
+ delete mode 100644 drivers/staging/brcm80211/include/bcmnvram.h
+ delete mode 100644 drivers/staging/brcm80211/include/bcmotp.h
+ delete mode 100644 drivers/staging/brcm80211/include/bcmsdh.h
+ delete mode 100644 drivers/staging/brcm80211/include/bcmsdpcm.h
+ delete mode 100644 drivers/staging/brcm80211/include/bcmsrom.h
+ delete mode 100644 drivers/staging/brcm80211/include/bcmsrom_fmt.h
+ delete mode 100644 drivers/staging/brcm80211/include/bcmutils.h
+ delete mode 100644 drivers/staging/brcm80211/include/bcmwifi.h
+ delete mode 100644 drivers/staging/brcm80211/include/hnddma.h
+ delete mode 100644 drivers/staging/brcm80211/include/hndsoc.h
+ delete mode 100644 drivers/staging/brcm80211/include/nicpci.h
+ delete mode 100644 drivers/staging/brcm80211/include/pci_core.h
+ delete mode 100644 drivers/staging/brcm80211/include/pcicfg.h
+ delete mode 100644 drivers/staging/brcm80211/include/pcie_core.h
+ delete mode 100644 drivers/staging/brcm80211/include/proto/802.11.h
+ delete mode 100644 drivers/staging/brcm80211/include/proto/bcmeth.h
+ delete mode 100644 drivers/staging/brcm80211/include/proto/bcmevent.h
+ delete mode 100644 drivers/staging/brcm80211/include/sbchipc.h
+ delete mode 100644 drivers/staging/brcm80211/include/sbconfig.h
+ delete mode 100644 drivers/staging/brcm80211/include/sbhnddma.h
+ delete mode 100644 drivers/staging/brcm80211/include/sbsdio.h
+ delete mode 100644 drivers/staging/brcm80211/include/sbsdpcmdev.h
+ delete mode 100644 drivers/staging/brcm80211/include/sdio.h
+ delete mode 100644 drivers/staging/brcm80211/include/wlioctl.h
+ delete mode 100644 drivers/staging/brcm80211/util/Makefile
+ delete mode 100644 drivers/staging/brcm80211/util/bcmutils.c
+ delete mode 100644 drivers/staging/brcm80211/util/bcmwifi.c
+
+diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
+index 196284d..f73909f 100644
+--- a/drivers/staging/Kconfig
++++ b/drivers/staging/Kconfig
+@@ -48,8 +48,6 @@ source "drivers/staging/wlan-ng/Kconfig"
+
+ source "drivers/staging/echo/Kconfig"
+
+-source "drivers/staging/brcm80211/Kconfig"
+-
+ source "drivers/staging/comedi/Kconfig"
+
+ source "drivers/staging/olpc_dcon/Kconfig"
+diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
+index fa41b9c..482897c 100644
+--- a/drivers/staging/Makefile
++++ b/drivers/staging/Makefile
+@@ -16,8 +16,6 @@ obj-$(CONFIG_USBIP_CORE) += usbip/
+ obj-$(CONFIG_W35UND) += winbond/
+ obj-$(CONFIG_PRISM2_USB) += wlan-ng/
+ obj-$(CONFIG_ECHO) += echo/
+-obj-$(CONFIG_BRCMSMAC) += brcm80211/
+-obj-$(CONFIG_BRCMFMAC) += brcm80211/
+ obj-$(CONFIG_COMEDI) += comedi/
+ obj-$(CONFIG_FB_OLPC_DCON) += olpc_dcon/
+ obj-$(CONFIG_ASUS_OLED) += asus_oled/
+diff --git a/drivers/staging/brcm80211/Kconfig b/drivers/staging/brcm80211/Kconfig
+deleted file mode 100644
+index 379cf16..0000000
+--- a/drivers/staging/brcm80211/Kconfig
++++ /dev/null
+@@ -1,40 +0,0 @@
+-config BRCMUTIL
+- tristate
+- default n
+-
+-config BRCMSMAC
+- tristate "Broadcom IEEE802.11n PCIe SoftMAC WLAN driver"
+- default n
+- depends on PCI
+- depends on WLAN && MAC80211
+- depends on X86 || MIPS
+- select BRCMUTIL
+- select FW_LOADER
+- select CRC_CCITT
+- ---help---
+- This module adds support for PCIe wireless adapters based on Broadcom
+- IEEE802.11n SoftMAC chipsets. If you choose to build a module, it'll
+- be called brcmsmac.ko.
+-
+-config BRCMFMAC
+- tristate "Broadcom IEEE802.11n embedded FullMAC WLAN driver"
+- default n
+- depends on MMC
+- depends on WLAN && CFG80211
+- depends on X86 || MIPS
+- select BRCMUTIL
+- select FW_LOADER
+- select WIRELESS_EXT
+- select WEXT_PRIV
+- ---help---
+- This module adds support for embedded wireless adapters based on
+- Broadcom IEEE802.11n FullMAC chipsets. This driver uses the kernel's
+- wireless extensions subsystem. If you choose to build a module,
+- it'll be called brcmfmac.ko.
+-
+-config BRCMDBG
+- bool "Broadcom driver debug functions"
+- default n
+- depends on BRCMSMAC || BRCMFMAC
+- ---help---
+- Selecting this enables additional code for debug purposes.
+diff --git a/drivers/staging/brcm80211/Makefile b/drivers/staging/brcm80211/Makefile
+deleted file mode 100644
+index e7b3f27..0000000
+--- a/drivers/staging/brcm80211/Makefile
++++ /dev/null
+@@ -1,24 +0,0 @@
+-#
+-# Makefile fragment for Broadcom 802.11n Networking Device Driver
+-#
+-# Copyright (c) 2010 Broadcom Corporation
+-#
+-# 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.
+-
+-# common flags
+-subdir-ccflags-y := -DBCMDMA32
+-subdir-ccflags-$(CONFIG_BRCMDBG) += -DBCMDBG -DBCMDBG_ASSERT
+-
+-obj-$(CONFIG_BRCMUTIL) += util/
+-obj-$(CONFIG_BRCMFMAC) += brcmfmac/
+-obj-$(CONFIG_BRCMSMAC) += brcmsmac/
+diff --git a/drivers/staging/brcm80211/README b/drivers/staging/brcm80211/README
+deleted file mode 100644
+index 8ad5586..0000000
+--- a/drivers/staging/brcm80211/README
++++ /dev/null
+@@ -1,64 +0,0 @@
+-Broadcom brcmsmac (mac80211-based softmac PCIe) and brcmfmac (SDIO) drivers.
+-
+-Completely open source host drivers, no binary object files.
+-
+-Support for the following chips:
+-===============================
+-
+- brcmsmac (PCIe)
+- Name Device ID
+- BCM4313 0x4727
+- BCM43224 0x4353
+- BCM43225 0x4357
+-
+- brcmfmac (SDIO)
+- Name
+- BCM4329
+-
+-Both brcmsmac and brcmfmac drivers require firmware files that need to be
+-separately downloaded.
+-
+-Firmware
+-======================
+-Firmware is available from the Linux firmware repository at:
+-
+- git://git.kernel.org/pub/scm/linux/kernel/git/dwmw2/linux-firmware.git
+- http://git.kernel.org/?p=linux/kernel/git/dwmw2/linux-firmware.git
+- https://git.kernel.org/?p=linux/kernel/git/dwmw2/linux-firmware.git
+-
+-
+-===============================================================
+-Broadcom brcmsmac driver
+-===============================================================
+-- Support for both 32 and 64 bit Linux kernels
+-
+-
+-Firmware installation
+-======================
+-Copy brcm/bcm43xx-0.fw and brcm/bcm43xx_hdr-0.fw to
+-/lib/firmware/brcm (or wherever firmware is normally installed
+-on your system).
+-
+-
+-===============================================================
+-Broadcom brcmfmac driver
+-===============================================================
+-- Support for 32 bit Linux kernel, 64 bit untested
+-
+-
+-Firmware installation
+-======================
+-Copy brcm/bcm4329-fullmac-4.bin and brcm/bcm4329-fullmac-4.txt
+-to /lib/firmware/brcm (or wherever firmware is normally installed on your
+-system).
+-
+-
+-Contact Info:
+-=============
+-Brett Rudley brudley@broadcom.com
+-Henry Ptasinski henryp@broadcom.com
+-Dowan Kim dowan@broadcom.com
+-Roland Vossen rvossen@broadcom.com
+-Arend van Spriel arend@broadcom.com
+-
+-For more info, refer to: http://linuxwireless.org/en/users/Drivers/brcm80211
+diff --git a/drivers/staging/brcm80211/TODO b/drivers/staging/brcm80211/TODO
+deleted file mode 100644
+index e9c1393..0000000
+--- a/drivers/staging/brcm80211/TODO
++++ /dev/null
+@@ -1,15 +0,0 @@
+-To Do List for Broadcom Mac80211 driver before getting in mainline
+-
+-Bugs
+-====
+-- Oops on AMPDU traffic, to be solved by new ucode (currently under test)
+-
+-brcmfmac and brcmsmac
+-=====================
+-- ASSERTS not allowed in mainline, replace by warning + error handling
+-- Replace printk and WL_ERROR() with proper routines
+-
+-brcmfmac
+-=====================
+-- Replace driver's proprietary ssb interface with generic kernel ssb module
+-- Build and test on 64 bit linux kernel
+diff --git a/drivers/staging/brcm80211/brcmfmac/Makefile b/drivers/staging/brcm80211/brcmfmac/Makefile
+deleted file mode 100644
+index c5ec562..0000000
+--- a/drivers/staging/brcm80211/brcmfmac/Makefile
++++ /dev/null
+@@ -1,56 +0,0 @@
+-#
+-# Makefile fragment for Broadcom 802.11n Networking Device Driver
+-#
+-# Copyright (c) 2010 Broadcom Corporation
+-#
+-# 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.
+-
+-ccflags-y := \
+- -DARP_OFFLOAD_SUPPORT \
+- -DBCMLXSDMMC \
+- -DBCMPLATFORM_BUS \
+- -DBCMSDIO \
+- -DBDC \
+- -DBRCM_FULLMAC \
+- -DDHD_FIRSTREAD=64 \
+- -DDHD_SCHED \
+- -DDHD_SDALIGN=64 \
+- -DEMBEDDED_PLATFORM \
+- -DMAX_HDR_READ=64 \
+- -DMMC_SDIO_ABORT \
+- -DPKT_FILTER_SUPPORT \
+- -DSHOW_EVENTS \
+- -DTOE
+-
+-ccflags-$(CONFIG_BRCMDBG) += -DDHD_DEBUG
+-
+-ccflags-y += \
+- -Idrivers/staging/brcm80211/brcmfmac \
+- -Idrivers/staging/brcm80211/include
+-
+-DHDOFILES = \
+- wl_cfg80211.o \
+- wl_iw.o \
+- dhd_cdc.o \
+- dhd_common.o \
+- dhd_custom_gpio.o \
+- dhd_sdio.o \
+- dhd_linux.o \
+- dhd_linux_sched.o \
+- bcmsdh.o \
+- bcmsdh_linux.o \
+- bcmsdh_sdmmc.o \
+- bcmsdh_sdmmc_linux.o
+-
+-obj-$(CONFIG_BRCMFMAC) += brcmfmac.o
+-brcmfmac-objs += $(DHDOFILES)
+diff --git a/drivers/staging/brcm80211/brcmfmac/README b/drivers/staging/brcm80211/brcmfmac/README
+deleted file mode 100644
+index 139597f..0000000
+--- a/drivers/staging/brcm80211/brcmfmac/README
++++ /dev/null
+@@ -1,2 +0,0 @@
+-
+-
+diff --git a/drivers/staging/brcm80211/brcmfmac/aiutils.c b/drivers/staging/brcm80211/brcmfmac/aiutils.c
+deleted file mode 100644
+index e648086..0000000
+--- a/drivers/staging/brcm80211/brcmfmac/aiutils.c
++++ /dev/null
+@@ -1 +0,0 @@
+-#include "../util/aiutils.c"
+diff --git a/drivers/staging/brcm80211/brcmfmac/bcmcdc.h b/drivers/staging/brcm80211/brcmfmac/bcmcdc.h
+deleted file mode 100644
+index ed4c4a5..0000000
+--- a/drivers/staging/brcm80211/brcmfmac/bcmcdc.h
++++ /dev/null
+@@ -1,98 +0,0 @@
+-/*
+- * Copyright (c) 2010 Broadcom Corporation
+- *
+- * 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/if_ether.h>
+-
+-typedef struct cdc_ioctl {
+- u32 cmd; /* ioctl command value */
+- u32 len; /* lower 16: output buflen; upper 16:
+- input buflen (excludes header) */
+- u32 flags; /* flag defns given below */
+- u32 status; /* status code returned from the device */
+-} cdc_ioctl_t;
+-
+-/* Max valid buffer size that can be sent to the dongle */
+-#define CDC_MAX_MSG_SIZE (ETH_FRAME_LEN+ETH_FCS_LEN)
+-
+-/* len field is divided into input and output buffer lengths */
+-#define CDCL_IOC_OUTLEN_MASK 0x0000FFFF /* maximum or expected
+- response length, */
+- /* excluding IOCTL header */
+-#define CDCL_IOC_OUTLEN_SHIFT 0
+-#define CDCL_IOC_INLEN_MASK 0xFFFF0000 /* input buffer length,
+- excluding IOCTL header */
+-#define CDCL_IOC_INLEN_SHIFT 16
+-
+-/* CDC flag definitions */
+-#define CDCF_IOC_ERROR 0x01 /* 0=success, 1=ioctl cmd failed */
+-#define CDCF_IOC_SET 0x02 /* 0=get, 1=set cmd */
+-#define CDCF_IOC_IF_MASK 0xF000 /* I/F index */
+-#define CDCF_IOC_IF_SHIFT 12
+-#define CDCF_IOC_ID_MASK 0xFFFF0000 /* used to uniquely id an ioctl
+- req/resp pairing */
+-#define CDCF_IOC_ID_SHIFT 16 /* # of bits of shift for ID Mask */
+-
+-#define CDC_IOC_IF_IDX(flags) \
+- (((flags) & CDCF_IOC_IF_MASK) >> CDCF_IOC_IF_SHIFT)
+-#define CDC_IOC_ID(flags) \
+- (((flags) & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT)
+-
+-#define CDC_GET_IF_IDX(hdr) \
+- ((int)((((hdr)->flags) & CDCF_IOC_IF_MASK) >> CDCF_IOC_IF_SHIFT))
+-#define CDC_SET_IF_IDX(hdr, idx) \
+- ((hdr)->flags = (((hdr)->flags & ~CDCF_IOC_IF_MASK) | \
+- ((idx) << CDCF_IOC_IF_SHIFT)))
+-
+-/*
+- * BDC header
+- *
+- * The BDC header is used on data packets to convey priority across USB.
+- */
+-
+-#define BDC_HEADER_LEN 4
+-
+-#define BDC_PROTO_VER 1 /* Protocol version */
+-
+-#define BDC_FLAG_VER_MASK 0xf0 /* Protocol version mask */
+-#define BDC_FLAG_VER_SHIFT 4 /* Protocol version shift */
+-
+-#define BDC_FLAG__UNUSED 0x03 /* Unassigned */
+-#define BDC_FLAG_SUM_GOOD 0x04 /* Dongle has verified good
+- RX checksums */
+-#define BDC_FLAG_SUM_NEEDED 0x08 /* Dongle needs to do TX checksums */
+-
+-#define BDC_PRIORITY_MASK 0x7
+-
+-#define BDC_FLAG2_FC_FLAG 0x10 /* flag to indicate if pkt contains */
+- /* FLOW CONTROL info only */
+-#define BDC_PRIORITY_FC_SHIFT 4 /* flow control info shift */
+-
+-#define BDC_FLAG2_IF_MASK 0x0f /* APSTA: interface on which the
+- packet was received */
+-#define BDC_FLAG2_IF_SHIFT 0
+-
+-#define BDC_GET_IF_IDX(hdr) \
+- ((int)((((hdr)->flags2) & BDC_FLAG2_IF_MASK) >> BDC_FLAG2_IF_SHIFT))
+-#define BDC_SET_IF_IDX(hdr, idx) \
+- ((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | \
+- ((idx) << BDC_FLAG2_IF_SHIFT)))
+-
+-struct bdc_header {
+- u8 flags; /* Flags */
+- u8 priority; /* 802.1d Priority 0:2 bits, 4:7 flow
+- control info for usb */
+- u8 flags2;
+- u8 rssi;
+-};
+diff --git a/drivers/staging/brcm80211/brcmfmac/bcmchip.h b/drivers/staging/brcm80211/brcmfmac/bcmchip.h
+deleted file mode 100644
+index c0d4c3b..0000000
+--- a/drivers/staging/brcm80211/brcmfmac/bcmchip.h
++++ /dev/null
+@@ -1,35 +0,0 @@
+-/*
+- * Copyright (c) 2011 Broadcom Corporation
+- *
+- * 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 _bcmchip_h_
+-#define _bcmchip_h_
+-
+-/* Core reg address translation */
+-#define CORE_CC_REG(base, field) (base + offsetof(chipcregs_t, field))
+-#define CORE_BUS_REG(base, field) (base + offsetof(sdpcmd_regs_t, field))
+-#define CORE_SB(base, field) \
+- (base + SBCONFIGOFF + offsetof(sbconfig_t, field))
+-
+-/* bcm4329 */
+-/* SDIO device core, ID 0x829 */
+-#define BCM4329_CORE_BUS_BASE 0x18011000
+-/* internal memory core, ID 0x80e */
+-#define BCM4329_CORE_SOCRAM_BASE 0x18003000
+-/* ARM Cortex M3 core, ID 0x82a */
+-#define BCM4329_CORE_ARM_BASE 0x18002000
+-#define BCM4329_RAMSIZE 0x48000
+-
+-#endif /* _bcmchip_h_ */
+diff --git a/drivers/staging/brcm80211/brcmfmac/bcmsdbus.h b/drivers/staging/brcm80211/brcmfmac/bcmsdbus.h
+deleted file mode 100644
+index 53c3291..0000000
+--- a/drivers/staging/brcm80211/brcmfmac/bcmsdbus.h
++++ /dev/null
+@@ -1,113 +0,0 @@
+-/*
+- * Copyright (c) 2010 Broadcom Corporation
+- *
+- * 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 _sdio_api_h_
+-#define _sdio_api_h_
+-
+-#define SDIOH_API_RC_SUCCESS (0x00)
+-#define SDIOH_API_RC_FAIL (0x01)
+-#define SDIOH_API_SUCCESS(status) (status == 0)
+-
+-#define SDIOH_READ 0 /* Read request */
+-#define SDIOH_WRITE 1 /* Write request */
+-
+-#define SDIOH_DATA_FIX 0 /* Fixed addressing */
+-#define SDIOH_DATA_INC 1 /* Incremental addressing */
+-
+-#define SDIOH_CMD_TYPE_NORMAL 0 /* Normal command */
+-#define SDIOH_CMD_TYPE_APPEND 1 /* Append command */
+-#define SDIOH_CMD_TYPE_CUTTHRU 2 /* Cut-through command */
+-
+-#define SDIOH_DATA_PIO 0 /* PIO mode */
+-#define SDIOH_DATA_DMA 1 /* DMA mode */
+-
+-typedef int SDIOH_API_RC;
+-
+-/* SDio Host structure */
+-typedef struct sdioh_info sdioh_info_t;
+-
+-/* callback function, taking one arg */
+-typedef void (*sdioh_cb_fn_t) (void *);
+-
+-/* attach, return handler on success, NULL if failed.
+- * The handler shall be provided by all subsequent calls. No local cache
+- * cfghdl points to the starting address of pci device mapped memory
+- */
+-extern sdioh_info_t *sdioh_attach(void *cfghdl, uint irq);
+-extern SDIOH_API_RC sdioh_detach(sdioh_info_t *si);
+-extern SDIOH_API_RC sdioh_interrupt_register(sdioh_info_t *si,
+- sdioh_cb_fn_t fn, void *argh);
+-extern SDIOH_API_RC sdioh_interrupt_deregister(sdioh_info_t *si);
+-
+-/* query whether SD interrupt is enabled or not */
+-extern SDIOH_API_RC sdioh_interrupt_query(sdioh_info_t *si, bool *onoff);
+-
+-/* enable or disable SD interrupt */
+-extern SDIOH_API_RC sdioh_interrupt_set(sdioh_info_t *si, bool enable_disable);
+-
+-#if defined(DHD_DEBUG)
+-extern bool sdioh_interrupt_pending(sdioh_info_t *si);
+-#endif
+-
+-extern int sdioh_claim_host_and_lock(sdioh_info_t *si);
+-extern int sdioh_release_host_and_unlock(sdioh_info_t *si);
+-
+-/* read or write one byte using cmd52 */
+-extern SDIOH_API_RC sdioh_request_byte(sdioh_info_t *si, uint rw, uint fnc,
+- uint addr, u8 *byte);
+-
+-/* read or write 2/4 bytes using cmd53 */
+-extern SDIOH_API_RC sdioh_request_word(sdioh_info_t *si, uint cmd_type,
+- uint rw, uint fnc, uint addr,
+- u32 *word, uint nbyte);
+-
+-/* read or write any buffer using cmd53 */
+-extern SDIOH_API_RC sdioh_request_buffer(sdioh_info_t *si, uint pio_dma,
+- uint fix_inc, uint rw, uint fnc_num,
+- u32 addr, uint regwidth,
+- u32 buflen, u8 *buffer,
+- struct sk_buff *pkt);
+-
+-/* get cis data */
+-extern SDIOH_API_RC sdioh_cis_read(sdioh_info_t *si, uint fuc, u8 *cis,
+- u32 length);
+-
+-extern SDIOH_API_RC sdioh_cfg_read(sdioh_info_t *si, uint fuc, u32 addr,
+- u8 *data);
+-extern SDIOH_API_RC sdioh_cfg_write(sdioh_info_t *si, uint fuc, u32 addr,
+- u8 *data);
+-
+-/* query number of io functions */
+-extern uint sdioh_query_iofnum(sdioh_info_t *si);
+-
+-/* handle iovars */
+-extern int sdioh_iovar_op(sdioh_info_t *si, const char *name,
+- void *params, int plen, void *arg, int len, bool set);
+-
+-/* Issue abort to the specified function and clear controller as needed */
+-extern int sdioh_abort(sdioh_info_t *si, uint fnc);
+-
+-/* Start and Stop SDIO without re-enumerating the SD card. */
+-extern int sdioh_start(sdioh_info_t *si, int stage);
+-extern int sdioh_stop(sdioh_info_t *si);
+-
+-/* Reset and re-initialize the device */
+-extern int sdioh_sdio_reset(sdioh_info_t *si);
+-
+-/* Helper function */
+-void *bcmsdh_get_sdioh(bcmsdh_info_t *sdh);
+-
+-#endif /* _sdio_api_h_ */
+diff --git a/drivers/staging/brcm80211/brcmfmac/bcmsdh.c b/drivers/staging/brcm80211/brcmfmac/bcmsdh.c
+deleted file mode 100644
+index 3750fcf..0000000
+--- a/drivers/staging/brcm80211/brcmfmac/bcmsdh.c
++++ /dev/null
+@@ -1,631 +0,0 @@
+-/*
+- * Copyright (c) 2010 Broadcom Corporation
+- *
+- * 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.
+- */
+-/* ****************** BCMSDH Interface Functions *************************** */
+-
+-#include <linux/types.h>
+-#include <linux/netdevice.h>
+-#include <linux/pci_ids.h>
+-#include <bcmdefs.h>
+-#include <bcmdevs.h>
+-#include <bcmutils.h>
+-#include <hndsoc.h>
+-
+-#include <bcmsdh.h> /* BRCM API for SDIO
+- clients (such as wl, dhd) */
+-#include <bcmsdbus.h> /* common SDIO/controller interface */
+-#include <sbsdio.h> /* BRCM sdio device core */
+-
+-#include <sdio.h> /* sdio spec */
+-#include "dngl_stats.h"
+-#include "dhd.h"
+-
+-#define SDIOH_API_ACCESS_RETRY_LIMIT 2
+-const uint bcmsdh_msglevel = BCMSDH_ERROR_VAL;
+-
+-struct bcmsdh_info {
+- bool init_success; /* underlying driver successfully attached */
+- void *sdioh; /* handler for sdioh */
+- u32 vendevid; /* Target Vendor and Device ID on SD bus */
+- bool regfail; /* Save status of last
+- reg_read/reg_write call */
+- u32 sbwad; /* Save backplane window address */
+-};
+-/* local copy of bcm sd handler */
+-bcmsdh_info_t *l_bcmsdh;
+-
+-#if defined(OOB_INTR_ONLY) && defined(HW_OOB)
+-extern int sdioh_enable_hw_oob_intr(void *sdioh, bool enable);
+-
+-void bcmsdh_enable_hw_oob_intr(bcmsdh_info_t *sdh, bool enable)
+-{
+- sdioh_enable_hw_oob_intr(sdh->sdioh, enable);
+-}
+-#endif
+-
+-bcmsdh_info_t *bcmsdh_attach(void *cfghdl, void **regsva, uint irq)
+-{
+- bcmsdh_info_t *bcmsdh;
+-
+- bcmsdh = kzalloc(sizeof(bcmsdh_info_t), GFP_ATOMIC);
+- if (bcmsdh == NULL) {
+- BCMSDH_ERROR(("bcmsdh_attach: out of memory"));
+- return NULL;
+- }
+-
+- /* save the handler locally */
+- l_bcmsdh = bcmsdh;
+-
+- bcmsdh->sdioh = sdioh_attach(cfghdl, irq);
+- if (!bcmsdh->sdioh) {
+- bcmsdh_detach(bcmsdh);
+- return NULL;
+- }
+-
+- bcmsdh->init_success = true;
+-
+- *regsva = (u32 *) SI_ENUM_BASE;
+-
+- /* Report the BAR, to fix if needed */
+- bcmsdh->sbwad = SI_ENUM_BASE;
+- return bcmsdh;
+-}
+-
+-int bcmsdh_detach(void *sdh)
+-{
+- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
+-
+- if (bcmsdh != NULL) {
+- if (bcmsdh->sdioh) {
+- sdioh_detach(bcmsdh->sdioh);
+- bcmsdh->sdioh = NULL;
+- }
+- kfree(bcmsdh);
+- }
+-
+- l_bcmsdh = NULL;
+- return 0;
+-}
+-
+-int
+-bcmsdh_iovar_op(void *sdh, const char *name,
+- void *params, int plen, void *arg, int len, bool set)
+-{
+- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
+- return sdioh_iovar_op(bcmsdh->sdioh, name, params, plen, arg, len, set);
+-}
+-
+-bool bcmsdh_intr_query(void *sdh)
+-{
+- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
+- SDIOH_API_RC status;
+- bool on;
+-
+- ASSERT(bcmsdh);
+- status = sdioh_interrupt_query(bcmsdh->sdioh, &on);
+- if (SDIOH_API_SUCCESS(status))
+- return false;
+- else
+- return on;
+-}
+-
+-int bcmsdh_intr_enable(void *sdh)
+-{
+- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
+- SDIOH_API_RC status;
+- ASSERT(bcmsdh);
+-
+- status = sdioh_interrupt_set(bcmsdh->sdioh, true);
+- return SDIOH_API_SUCCESS(status) ? 0 : -EIO;
+-}
+-
+-int bcmsdh_intr_disable(void *sdh)
+-{
+- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
+- SDIOH_API_RC status;
+- ASSERT(bcmsdh);
+-
+- status = sdioh_interrupt_set(bcmsdh->sdioh, false);
+- return SDIOH_API_SUCCESS(status) ? 0 : -EIO;
+-}
+-
+-int bcmsdh_intr_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh)
+-{
+- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
+- SDIOH_API_RC status;
+- ASSERT(bcmsdh);
+-
+- status = sdioh_interrupt_register(bcmsdh->sdioh, fn, argh);
+- return SDIOH_API_SUCCESS(status) ? 0 : -EIO;
+-}
+-
+-int bcmsdh_intr_dereg(void *sdh)
+-{
+- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
+- SDIOH_API_RC status;
+- ASSERT(bcmsdh);
+-
+- status = sdioh_interrupt_deregister(bcmsdh->sdioh);
+- return SDIOH_API_SUCCESS(status) ? 0 : -EIO;
+-}
+-
+-#if defined(DHD_DEBUG)
+-bool bcmsdh_intr_pending(void *sdh)
+-{
+- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
+-
+- ASSERT(sdh);
+- return sdioh_interrupt_pending(bcmsdh->sdioh);
+-}
+-#endif
+-
+-int bcmsdh_devremove_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh)
+-{
+- ASSERT(sdh);
+-
+- /* don't support yet */
+- return -ENOTSUPP;
+-}
+-
+-u8 bcmsdh_cfg_read(void *sdh, uint fnc_num, u32 addr, int *err)
+-{
+- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
+- SDIOH_API_RC status;
+-#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
+- s32 retry = 0;
+-#endif
+- u8 data = 0;
+-
+- if (!bcmsdh)
+- bcmsdh = l_bcmsdh;
+-
+- ASSERT(bcmsdh->init_success);
+-
+-#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
+- do {
+- if (retry) /* wait for 1 ms till bus get settled down */
+- udelay(1000);
+-#endif
+- status =
+- sdioh_cfg_read(bcmsdh->sdioh, fnc_num, addr,
+- (u8 *) &data);
+-#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
+- } while (!SDIOH_API_SUCCESS(status)
+- && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
+-#endif
+- if (err)
+- *err = (SDIOH_API_SUCCESS(status) ? 0 : -EIO);
+-
+- BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n",
+- __func__, fnc_num, addr, data));
+-
+- return data;
+-}
+-
+-void
+-bcmsdh_cfg_write(void *sdh, uint fnc_num, u32 addr, u8 data, int *err)
+-{
+- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
+- SDIOH_API_RC status;
+-#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
+- s32 retry = 0;
+-#endif
+-
+- if (!bcmsdh)
+- bcmsdh = l_bcmsdh;
+-
+- ASSERT(bcmsdh->init_success);
+-
+-#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
+- do {
+- if (retry) /* wait for 1 ms till bus get settled down */
+- udelay(1000);
+-#endif
+- status =
+- sdioh_cfg_write(bcmsdh->sdioh, fnc_num, addr,
+- (u8 *) &data);
+-#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
+- } while (!SDIOH_API_SUCCESS(status)
+- && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
+-#endif
+- if (err)
+- *err = SDIOH_API_SUCCESS(status) ? 0 : -EIO;
+-
+- BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n",
+- __func__, fnc_num, addr, data));
+-}
+-
+-u32 bcmsdh_cfg_read_word(void *sdh, uint fnc_num, u32 addr, int *err)
+-{
+- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
+- SDIOH_API_RC status;
+- u32 data = 0;
+-
+- if (!bcmsdh)
+- bcmsdh = l_bcmsdh;
+-
+- ASSERT(bcmsdh->init_success);
+-
+- status =
+- sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL, SDIOH_READ,
+- fnc_num, addr, &data, 4);
+-
+- if (err)
+- *err = (SDIOH_API_SUCCESS(status) ? 0 : -EIO);
+-
+- BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, u32data = 0x%x\n",
+- __func__, fnc_num, addr, data));
+-
+- return data;
+-}
+-
+-void
+-bcmsdh_cfg_write_word(void *sdh, uint fnc_num, u32 addr, u32 data,
+- int *err)
+-{
+- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
+- SDIOH_API_RC status;
+-
+- if (!bcmsdh)
+- bcmsdh = l_bcmsdh;
+-
+- ASSERT(bcmsdh->init_success);
+-
+- status =
+- sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL,
+- SDIOH_WRITE, fnc_num, addr, &data, 4);
+-
+- if (err)
+- *err = (SDIOH_API_SUCCESS(status) ? 0 : -EIO);
+-
+- BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, u32data = 0x%x\n",
+- __func__, fnc_num, addr, data));
+-}
+-
+-int bcmsdh_cis_read(void *sdh, uint func, u8 * cis, uint length)
+-{
+- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
+- SDIOH_API_RC status;
+-
+- u8 *tmp_buf, *tmp_ptr;
+- u8 *ptr;
+- bool ascii = func & ~0xf;
+- func &= 0x7;
+-
+- if (!bcmsdh)
+- bcmsdh = l_bcmsdh;
+-
+- ASSERT(bcmsdh->init_success);
+- ASSERT(cis);
+- ASSERT(length <= SBSDIO_CIS_SIZE_LIMIT);
+-
+- status = sdioh_cis_read(bcmsdh->sdioh, func, cis, length);
+-
+- if (ascii) {
+- /* Move binary bits to tmp and format them
+- into the provided buffer. */
+- tmp_buf = kmalloc(length, GFP_ATOMIC);
+- if (tmp_buf == NULL) {
+- BCMSDH_ERROR(("%s: out of memory\n", __func__));
+- return -ENOMEM;
+- }
+- memcpy(tmp_buf, cis, length);
+- for (tmp_ptr = tmp_buf, ptr = cis; ptr < (cis + length - 4);
+- tmp_ptr++) {
+- ptr += sprintf((char *)ptr, "%.2x ", *tmp_ptr & 0xff);
+- if ((((tmp_ptr - tmp_buf) + 1) & 0xf) == 0)
+- ptr += sprintf((char *)ptr, "\n");
+- }
+- kfree(tmp_buf);
+- }
+-
+- return SDIOH_API_SUCCESS(status) ? 0 : -EIO;
+-}
+-
+-static int bcmsdhsdio_set_sbaddr_window(void *sdh, u32 address)
+-{
+- int err = 0;
+- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
+- bcmsdh_cfg_write(bcmsdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
+- (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
+- if (!err)
+- bcmsdh_cfg_write(bcmsdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRMID,
+- (address >> 16) & SBSDIO_SBADDRMID_MASK, &err);
+- if (!err)
+- bcmsdh_cfg_write(bcmsdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRHIGH,
+- (address >> 24) & SBSDIO_SBADDRHIGH_MASK,
+- &err);
+-
+- return err;
+-}
+-
+-u32 bcmsdh_reg_read(void *sdh, u32 addr, uint size)
+-{
+- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
+- SDIOH_API_RC status;
+- u32 word = 0;
+- uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
+-
+- BCMSDH_INFO(("%s:fun = 1, addr = 0x%x, ", __func__, addr));
+-
+- if (!bcmsdh)
+- bcmsdh = l_bcmsdh;
+-
+- ASSERT(bcmsdh->init_success);
+-
+- if (bar0 != bcmsdh->sbwad) {
+- if (bcmsdhsdio_set_sbaddr_window(bcmsdh, bar0))
+- return 0xFFFFFFFF;
+-
+- bcmsdh->sbwad = bar0;
+- }
+-
+- addr &= SBSDIO_SB_OFT_ADDR_MASK;
+- if (size == 4)
+- addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+-
+- status = sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL,
+- SDIOH_READ, SDIO_FUNC_1, addr, &word, size);
+-
+- bcmsdh->regfail = !(SDIOH_API_SUCCESS(status));
+-
+- BCMSDH_INFO(("u32data = 0x%x\n", word));
+-
+- /* if ok, return appropriately masked word */
+- if (SDIOH_API_SUCCESS(status)) {
+- switch (size) {
+- case sizeof(u8):
+- return word & 0xff;
+- case sizeof(u16):
+- return word & 0xffff;
+- case sizeof(u32):
+- return word;
+- default:
+- bcmsdh->regfail = true;
+-
+- }
+- }
+-
+- /* otherwise, bad sdio access or invalid size */
+- BCMSDH_ERROR(("%s: error reading addr 0x%04x size %d\n", __func__,
+- addr, size));
+- return 0xFFFFFFFF;
+-}
+-
+-u32 bcmsdh_reg_write(void *sdh, u32 addr, uint size, u32 data)
+-{
+- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
+- SDIOH_API_RC status;
+- uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
+- int err = 0;
+-
+- BCMSDH_INFO(("%s:fun = 1, addr = 0x%x, uint%ddata = 0x%x\n",
+- __func__, addr, size * 8, data));
+-
+- if (!bcmsdh)
+- bcmsdh = l_bcmsdh;
+-
+- ASSERT(bcmsdh->init_success);
+-
+- if (bar0 != bcmsdh->sbwad) {
+- err = bcmsdhsdio_set_sbaddr_window(bcmsdh, bar0);
+- if (err)
+- return err;
+-
+- bcmsdh->sbwad = bar0;
+- }
+-
+- addr &= SBSDIO_SB_OFT_ADDR_MASK;
+- if (size == 4)
+- addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+- status =
+- sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL,
+- SDIOH_WRITE, SDIO_FUNC_1, addr, &data, size);
+- bcmsdh->regfail = !(SDIOH_API_SUCCESS(status));
+-
+- if (SDIOH_API_SUCCESS(status))
+- return 0;
+-
+- BCMSDH_ERROR(("%s: error writing 0x%08x to addr 0x%04x size %d\n",
+- __func__, data, addr, size));
+- return 0xFFFFFFFF;
+-}
+-
+-bool bcmsdh_regfail(void *sdh)
+-{
+- return ((bcmsdh_info_t *) sdh)->regfail;
+-}
+-
+-int
+-bcmsdh_recv_buf(void *sdh, u32 addr, uint fn, uint flags,
+- u8 *buf, uint nbytes, struct sk_buff *pkt,
+- bcmsdh_cmplt_fn_t complete, void *handle)
+-{
+- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
+- SDIOH_API_RC status;
+- uint incr_fix;
+- uint width;
+- uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
+- int err = 0;
+-
+- ASSERT(bcmsdh);
+- ASSERT(bcmsdh->init_success);
+-
+- BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
+- __func__, fn, addr, nbytes));
+-
+- /* Async not implemented yet */
+- ASSERT(!(flags & SDIO_REQ_ASYNC));
+- if (flags & SDIO_REQ_ASYNC)
+- return -ENOTSUPP;
+-
+- if (bar0 != bcmsdh->sbwad) {
+- err = bcmsdhsdio_set_sbaddr_window(bcmsdh, bar0);
+- if (err)
+- return err;
+-
+- bcmsdh->sbwad = bar0;
+- }
+-
+- addr &= SBSDIO_SB_OFT_ADDR_MASK;
+-
+- incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
+- width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
+- if (width == 4)
+- addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+-
+- status = sdioh_request_buffer(bcmsdh->sdioh, SDIOH_DATA_PIO, incr_fix,
+- SDIOH_READ, fn, addr, width, nbytes, buf,
+- pkt);
+-
+- return SDIOH_API_SUCCESS(status) ? 0 : -EIO;
+-}
+-
+-int
+-bcmsdh_send_buf(void *sdh, u32 addr, uint fn, uint flags,
+- u8 *buf, uint nbytes, void *pkt,
+- bcmsdh_cmplt_fn_t complete, void *handle)
+-{
+- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
+- SDIOH_API_RC status;
+- uint incr_fix;
+- uint width;
+- uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
+- int err = 0;
+-
+- ASSERT(bcmsdh);
+- ASSERT(bcmsdh->init_success);
+-
+- BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
+- __func__, fn, addr, nbytes));
+-
+- /* Async not implemented yet */
+- ASSERT(!(flags & SDIO_REQ_ASYNC));
+- if (flags & SDIO_REQ_ASYNC)
+- return -ENOTSUPP;
+-
+- if (bar0 != bcmsdh->sbwad) {
+- err = bcmsdhsdio_set_sbaddr_window(bcmsdh, bar0);
+- if (err)
+- return err;
+-
+- bcmsdh->sbwad = bar0;
+- }
+-
+- addr &= SBSDIO_SB_OFT_ADDR_MASK;
+-
+- incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
+- width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
+- if (width == 4)
+- addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+-
+- status = sdioh_request_buffer(bcmsdh->sdioh, SDIOH_DATA_PIO, incr_fix,
+- SDIOH_WRITE, fn, addr, width, nbytes, buf,
+- pkt);
+-
+- return SDIOH_API_SUCCESS(status) ? 0 : -EIO;
+-}
+-
+-int bcmsdh_rwdata(void *sdh, uint rw, u32 addr, u8 *buf, uint nbytes)
+-{
+- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
+- SDIOH_API_RC status;
+-
+- ASSERT(bcmsdh);
+- ASSERT(bcmsdh->init_success);
+- ASSERT((addr & SBSDIO_SBWINDOW_MASK) == 0);
+-
+- addr &= SBSDIO_SB_OFT_ADDR_MASK;
+- addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+-
+- status =
+- sdioh_request_buffer(bcmsdh->sdioh, SDIOH_DATA_PIO, SDIOH_DATA_INC,
+- (rw ? SDIOH_WRITE : SDIOH_READ), SDIO_FUNC_1,
+- addr, 4, nbytes, buf, NULL);
+-
+- return SDIOH_API_SUCCESS(status) ? 0 : -EIO;
+-}
+-
+-int bcmsdh_abort(void *sdh, uint fn)
+-{
+- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
+-
+- return sdioh_abort(bcmsdh->sdioh, fn);
+-}
+-
+-int bcmsdh_start(void *sdh, int stage)
+-{
+- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
+-
+- return sdioh_start(bcmsdh->sdioh, stage);
+-}
+-
+-int bcmsdh_stop(void *sdh)
+-{
+- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
+-
+- return sdioh_stop(bcmsdh->sdioh);
+-}
+-
+-int bcmsdh_query_device(void *sdh)
+-{
+- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
+- bcmsdh->vendevid = (PCI_VENDOR_ID_BROADCOM << 16) | 0;
+- return bcmsdh->vendevid;
+-}
+-
+-uint bcmsdh_query_iofnum(void *sdh)
+-{
+- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
+-
+- if (!bcmsdh)
+- bcmsdh = l_bcmsdh;
+-
+- return sdioh_query_iofnum(bcmsdh->sdioh);
+-}
+-
+-int bcmsdh_reset(bcmsdh_info_t *sdh)
+-{
+- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
+-
+- return sdioh_sdio_reset(bcmsdh->sdioh);
+-}
+-
+-void *bcmsdh_get_sdioh(bcmsdh_info_t *sdh)
+-{
+- ASSERT(sdh);
+- return sdh->sdioh;
+-}
+-
+-/* Function to pass device-status bits to DHD. */
+-u32 bcmsdh_get_dstatus(void *sdh)
+-{
+- return 0;
+-}
+-
+-u32 bcmsdh_cur_sbwad(void *sdh)
+-{
+- bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
+-
+- if (!bcmsdh)
+- bcmsdh = l_bcmsdh;
+-
+- return bcmsdh->sbwad;
+-}
+-
+-void bcmsdh_chipinfo(void *sdh, u32 chip, u32 chiprev)
+-{
+- return;
+-}
+diff --git a/drivers/staging/brcm80211/brcmfmac/bcmsdh_linux.c b/drivers/staging/brcm80211/brcmfmac/bcmsdh_linux.c
+deleted file mode 100644
+index 465f623..0000000
+--- a/drivers/staging/brcm80211/brcmfmac/bcmsdh_linux.c
++++ /dev/null
+@@ -1,386 +0,0 @@
+-/*
+- * Copyright (c) 2010 Broadcom Corporation
+- *
+- * 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.
+- */
+-
+-/**
+- * @file bcmsdh_linux.c
+- */
+-
+-#define __UNDEF_NO_VERSION__
+-
+-#include <linux/netdevice.h>
+-#include <linux/pci.h>
+-#include <linux/completion.h>
+-
+-#include <pcicfg.h>
+-#include <bcmdefs.h>
+-#include <bcmdevs.h>
+-#include <bcmutils.h>
+-
+-#if defined(OOB_INTR_ONLY)
+-#include <linux/irq.h>
+-extern void dhdsdio_isr(void *args);
+-#include <dngl_stats.h>
+-#include <dhd.h>
+-#endif /* defined(OOB_INTR_ONLY) */
+-#if defined(CONFIG_MACH_SANDGATE2G) || defined(CONFIG_MACH_LOGICPD_PXA270)
+-#if !defined(BCMPLATFORM_BUS)
+-#define BCMPLATFORM_BUS
+-#endif /* !defined(BCMPLATFORM_BUS) */
+-
+-#include <linux/platform_device.h>
+-#endif /* CONFIG_MACH_SANDGATE2G */
+-
+-#include "dngl_stats.h"
+-#include "dhd.h"
+-
+-/**
+- * SDIO Host Controller info
+- */
+-typedef struct bcmsdh_hc bcmsdh_hc_t;
+-
+-struct bcmsdh_hc {
+- bcmsdh_hc_t *next;
+-#ifdef BCMPLATFORM_BUS
+- struct device *dev; /* platform device handle */
+-#else
+- struct pci_dev *dev; /* pci device handle */
+-#endif /* BCMPLATFORM_BUS */
+- void *regs; /* SDIO Host Controller address */
+- bcmsdh_info_t *sdh; /* SDIO Host Controller handle */
+- void *ch;
+- unsigned int oob_irq;
+- unsigned long oob_flags; /* OOB Host specifiction
+- as edge and etc */
+- bool oob_irq_registered;
+-#if defined(OOB_INTR_ONLY)
+- spinlock_t irq_lock;
+-#endif
+-};
+-static bcmsdh_hc_t *sdhcinfo;
+-
+-/* driver info, initialized when bcmsdh_register is called */
+-static bcmsdh_driver_t drvinfo = { NULL, NULL };
+-
+-/* debugging macros */
+-#define SDLX_MSG(x)
+-
+-/**
+- * Checks to see if vendor and device IDs match a supported SDIO Host Controller.
+- */
+-bool bcmsdh_chipmatch(u16 vendor, u16 device)
+-{
+- /* Add other vendors and devices as required */
+-
+-#ifdef BCMSDIOH_STD
+- /* Check for Arasan host controller */
+- if (vendor == VENDOR_SI_IMAGE)
+- return true;
+-
+- /* Check for BRCM 27XX Standard host controller */
+- if (device == BCM27XX_SDIOH_ID && vendor == PCI_VENDOR_ID_BROADCOM)
+- return true;
+-
+- /* Check for BRCM Standard host controller */
+- if (device == SDIOH_FPGA_ID && vendor == PCI_VENDOR_ID_BROADCOM)
+- return true;
+-
+- /* Check for TI PCIxx21 Standard host controller */
+- if (device == PCIXX21_SDIOH_ID && vendor == VENDOR_TI)
+- return true;
+-
+- if (device == PCIXX21_SDIOH0_ID && vendor == VENDOR_TI)
+- return true;
+-
+- /* Ricoh R5C822 Standard SDIO Host */
+- if (device == R5C822_SDIOH_ID && vendor == VENDOR_RICOH)
+- return true;
+-
+- /* JMicron Standard SDIO Host */
+- if (device == JMICRON_SDIOH_ID && vendor == VENDOR_JMICRON)
+- return true;
+-#endif /* BCMSDIOH_STD */
+-#ifdef BCMSDIOH_SPI
+- /* This is the PciSpiHost. */
+- if (device == SPIH_FPGA_ID && vendor == PCI_VENDOR_ID_BROADCOM) {
+- return true;
+- }
+-#endif /* BCMSDIOH_SPI */
+-
+- return false;
+-}
+-
+-#if defined(BCMPLATFORM_BUS)
+-#if defined(BCMLXSDMMC)
+-/* forward declarations */
+-int bcmsdh_probe(struct device *dev);
+-EXPORT_SYMBOL(bcmsdh_probe);
+-
+-int bcmsdh_remove(struct device *dev);
+-EXPORT_SYMBOL(bcmsdh_remove);
+-
+-#else
+-/* forward declarations */
+-static int __devinit bcmsdh_probe(struct device *dev);
+-static int __devexit bcmsdh_remove(struct device *dev);
+-#endif /* BCMLXSDMMC */
+-
+-#ifndef BCMLXSDMMC
+-static
+-#endif /* BCMLXSDMMC */
+-int bcmsdh_probe(struct device *dev)
+-{
+- bcmsdh_hc_t *sdhc = NULL;
+- unsigned long regs = 0;
+- bcmsdh_info_t *sdh = NULL;
+-#if !defined(BCMLXSDMMC) && defined(BCMPLATFORM_BUS)
+- struct platform_device *pdev;
+- struct resource *r;
+-#endif /* BCMLXSDMMC */
+- int irq = 0;
+- u32 vendevid;
+- unsigned long irq_flags = 0;
+-
+-#if !defined(BCMLXSDMMC) && defined(BCMPLATFORM_BUS)
+- pdev = to_platform_device(dev);
+- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- irq = platform_get_irq(pdev, 0);
+- if (!r || irq == NO_IRQ)
+- return -ENXIO;
+-#endif /* BCMLXSDMMC */
+-
+-#if defined(OOB_INTR_ONLY)
+-#ifdef HW_OOB
+- irq_flags =
+- IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL |
+- IORESOURCE_IRQ_SHAREABLE;
+-#else
+- irq_flags = IRQF_TRIGGER_FALLING;
+-#endif /* HW_OOB */
+- irq = dhd_customer_oob_irq_map(&irq_flags);
+- if (irq < 0) {
+- SDLX_MSG(("%s: Host irq is not defined\n", __func__));
+- return 1;
+- }
+-#endif /* defined(OOB_INTR_ONLY) */
+- /* allocate SDIO Host Controller state info */
+- sdhc = kzalloc(sizeof(bcmsdh_hc_t), GFP_ATOMIC);
+- if (!sdhc) {
+- SDLX_MSG(("%s: out of memory\n", __func__));
+- goto err;
+- }
+- sdhc->dev = (void *)dev;
+-
+-#ifdef BCMLXSDMMC
+- sdh = bcmsdh_attach((void *)0, (void **)®s, irq);
+- if (!sdh) {
+- SDLX_MSG(("%s: bcmsdh_attach failed\n", __func__));
+- goto err;
+- }
+-#else
+- sdh = bcmsdh_attach((void *)r->start, (void **)®s, irq);
+- if (!sdh) {
+- SDLX_MSG(("%s: bcmsdh_attach failed\n", __func__));
+- goto err;
+- }
+-#endif /* BCMLXSDMMC */
+- sdhc->sdh = sdh;
+- sdhc->oob_irq = irq;
+- sdhc->oob_flags = irq_flags;
+- sdhc->oob_irq_registered = false; /* to make sure.. */
+-#if defined(OOB_INTR_ONLY)
+- spin_lock_init(&sdhc->irq_lock);
+-#endif
+-
+- /* chain SDIO Host Controller info together */
+- sdhc->next = sdhcinfo;
+- sdhcinfo = sdhc;
+- /* Read the vendor/device ID from the CIS */
+- vendevid = bcmsdh_query_device(sdh);
+-
+- /* try to attach to the target device */
+- sdhc->ch = drvinfo.attach((vendevid >> 16), (vendevid & 0xFFFF),
+- 0, 0, 0, 0, (void *)regs, sdh);
+- if (!sdhc->ch) {
+- SDLX_MSG(("%s: device attach failed\n", __func__));
+- goto err;
+- }
+-
+- return 0;
+-
+- /* error handling */
+-err:
+- if (sdhc) {
+- if (sdhc->sdh)
+- bcmsdh_detach(sdhc->sdh);
+- kfree(sdhc);
+- }
+-
+- return -ENODEV;
+-}
+-
+-#ifndef BCMLXSDMMC
+-static
+-#endif /* BCMLXSDMMC */
+-int bcmsdh_remove(struct device *dev)
+-{
+- bcmsdh_hc_t *sdhc, *prev;
+-
+- sdhc = sdhcinfo;
+- drvinfo.detach(sdhc->ch);
+- bcmsdh_detach(sdhc->sdh);
+- /* find the SDIO Host Controller state for this pdev
+- and take it out from the list */
+- for (sdhc = sdhcinfo, prev = NULL; sdhc; sdhc = sdhc->next) {
+- if (sdhc->dev == (void *)dev) {
+- if (prev)
+- prev->next = sdhc->next;
+- else
+- sdhcinfo = NULL;
+- break;
+- }
+- prev = sdhc;
+- }
+- if (!sdhc) {
+- SDLX_MSG(("%s: failed\n", __func__));
+- return 0;
+- }
+-
+- /* release SDIO Host Controller info */
+- kfree(sdhc);
+-
+-#if !defined(BCMLXSDMMC)
+- dev_set_drvdata(dev, NULL);
+-#endif /* !defined(BCMLXSDMMC) */
+-
+- return 0;
+-}
+-#endif /* BCMPLATFORM_BUS */
+-
+-extern int sdio_function_init(void);
+-
+-int bcmsdh_register(bcmsdh_driver_t *driver)
+-{
+- drvinfo = *driver;
+-
+- SDLX_MSG(("Linux Kernel SDIO/MMC Driver\n"));
+- return sdio_function_init();
+-}
+-
+-extern void sdio_function_cleanup(void);
+-
+-void bcmsdh_unregister(void)
+-{
+- sdio_function_cleanup();
+-}
+-
+-#if defined(OOB_INTR_ONLY)
+-void bcmsdh_oob_intr_set(bool enable)
+-{
+- static bool curstate = 1;
+- unsigned long flags;
+-
+- spin_lock_irqsave(&sdhcinfo->irq_lock, flags);
+- if (curstate != enable) {
+- if (enable)
+- enable_irq(sdhcinfo->oob_irq);
+- else
+- disable_irq_nosync(sdhcinfo->oob_irq);
+- curstate = enable;
+- }
+- spin_unlock_irqrestore(&sdhcinfo->irq_lock, flags);
+-}
+-
+-static irqreturn_t wlan_oob_irq(int irq, void *dev_id)
+-{
+- dhd_pub_t *dhdp;
+-
+- dhdp = (dhd_pub_t *) dev_get_drvdata(sdhcinfo->dev);
+-
+- bcmsdh_oob_intr_set(0);
+-
+- if (dhdp == NULL) {
+- SDLX_MSG(("Out of band GPIO interrupt fired way too early\n"));
+- return IRQ_HANDLED;
+- }
+-
+- dhdsdio_isr((void *)dhdp->bus);
+-
+- return IRQ_HANDLED;
+-}
+-
+-int bcmsdh_register_oob_intr(void *dhdp)
+-{
+- int error = 0;
+-
+- SDLX_MSG(("%s Enter\n", __func__));
+-
+- sdhcinfo->oob_flags =
+- IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL |
+- IORESOURCE_IRQ_SHAREABLE;
+- dev_set_drvdata(sdhcinfo->dev, dhdp);
+-
+- if (!sdhcinfo->oob_irq_registered) {
+- SDLX_MSG(("%s IRQ=%d Type=%X\n", __func__,
+- (int)sdhcinfo->oob_irq, (int)sdhcinfo->oob_flags));
+- /* Refer to customer Host IRQ docs about
+- proper irqflags definition */
+- error =
+- request_irq(sdhcinfo->oob_irq, wlan_oob_irq,
+- sdhcinfo->oob_flags, "bcmsdh_sdmmc", NULL);
+- if (error)
+- return -ENODEV;
+-
+- irq_set_irq_wake(sdhcinfo->oob_irq, 1);
+- sdhcinfo->oob_irq_registered = true;
+- }
+-
+- return 0;
+-}
+-
+-void bcmsdh_unregister_oob_intr(void)
+-{
+- SDLX_MSG(("%s: Enter\n", __func__));
+-
+- irq_set_irq_wake(sdhcinfo->oob_irq, 0);
+- disable_irq(sdhcinfo->oob_irq); /* just in case.. */
+- free_irq(sdhcinfo->oob_irq, NULL);
+- sdhcinfo->oob_irq_registered = false;
+-}
+-#endif /* defined(OOB_INTR_ONLY) */
+-/* Module parameters specific to each host-controller driver */
+-
+-extern uint sd_msglevel; /* Debug message level */
+-module_param(sd_msglevel, uint, 0);
+-
+-extern uint sd_power; /* 0 = SD Power OFF,
+- 1 = SD Power ON. */
+-module_param(sd_power, uint, 0);
+-
+-extern uint sd_clock; /* SD Clock Control, 0 = SD Clock OFF,
+- 1 = SD Clock ON */
+-module_param(sd_clock, uint, 0);
+-
+-extern uint sd_divisor; /* Divisor (-1 means external clock) */
+-module_param(sd_divisor, uint, 0);
+-
+-extern uint sd_sdmode; /* Default is SD4, 0=SPI, 1=SD1, 2=SD4 */
+-module_param(sd_sdmode, uint, 0);
+-
+-extern uint sd_hiok; /* Ok to use hi-speed mode */
+-module_param(sd_hiok, uint, 0);
+-
+-extern uint sd_f2_blocksize;
+-module_param(sd_f2_blocksize, int, 0);
+diff --git a/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c
+deleted file mode 100644
+index c0ffbd3..0000000
+--- a/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c
++++ /dev/null
+@@ -1,1239 +0,0 @@
+-/*
+- * Copyright (c) 2010 Broadcom Corporation
+- *
+- * 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/types.h>
+-#include <linux/netdevice.h>
+-#include <bcmdefs.h>
+-#include <bcmdevs.h>
+-#include <bcmutils.h>
+-#include <sdio.h> /* SDIO Device and Protocol Specs */
+-#include <sdioh.h> /* SDIO Host Controller Specification */
+-#include <bcmsdbus.h> /* bcmsdh to/from specific controller APIs */
+-#include <sdiovar.h> /* ioctl/iovars */
+-
+-#include <linux/mmc/core.h>
+-#include <linux/mmc/sdio_func.h>
+-#include <linux/mmc/sdio_ids.h>
+-#include <linux/suspend.h>
+-
+-#include <dngl_stats.h>
+-#include <dhd.h>
+-
+-#include "bcmsdh_sdmmc.h"
+-
+-extern int sdio_function_init(void);
+-extern void sdio_function_cleanup(void);
+-
+-#if !defined(OOB_INTR_ONLY)
+-static void IRQHandler(struct sdio_func *func);
+-static void IRQHandlerF2(struct sdio_func *func);
+-#endif /* !defined(OOB_INTR_ONLY) */
+-static int sdioh_sdmmc_get_cisaddr(sdioh_info_t *sd, u32 regaddr);
+-extern int sdio_reset_comm(struct mmc_card *card);
+-
+-extern PBCMSDH_SDMMC_INSTANCE gInstance;
+-
+-uint sd_sdmode = SDIOH_MODE_SD4; /* Use SD4 mode by default */
+-uint sd_f2_blocksize = 512; /* Default blocksize */
+-
+-uint sd_divisor = 2; /* Default 48MHz/2 = 24MHz */
+-
+-uint sd_power = 1; /* Default to SD Slot powered ON */
+-uint sd_clock = 1; /* Default to SD Clock turned ON */
+-uint sd_hiok = false; /* Don't use hi-speed mode by default */
+-uint sd_msglevel = 0x01;
+-uint sd_use_dma = true;
+-DHD_PM_RESUME_WAIT_INIT(sdioh_request_byte_wait);
+-DHD_PM_RESUME_WAIT_INIT(sdioh_request_word_wait);
+-DHD_PM_RESUME_WAIT_INIT(sdioh_request_packet_wait);
+-DHD_PM_RESUME_WAIT_INIT(sdioh_request_buffer_wait);
+-
+-#define DMA_ALIGN_MASK 0x03
+-
+-int sdioh_sdmmc_card_regread(sdioh_info_t *sd, int func, u32 regaddr,
+- int regsize, u32 *data);
+-
+-void sdioh_sdio_set_host_pm_flags(int flag)
+-{
+- if (sdio_set_host_pm_flags(gInstance->func[1], flag))
+- printk(KERN_ERR "%s: Failed to set pm_flags 0x%08x\n",\
+- __func__, (unsigned int)flag);
+-}
+-
+-static int sdioh_sdmmc_card_enablefuncs(sdioh_info_t *sd)
+-{
+- int err_ret;
+- u32 fbraddr;
+- u8 func;
+-
+- sd_trace(("%s\n", __func__));
+-
+- /* Get the Card's common CIS address */
+- sd->com_cis_ptr = sdioh_sdmmc_get_cisaddr(sd, SDIOD_CCCR_CISPTR_0);
+- sd->func_cis_ptr[0] = sd->com_cis_ptr;
+- sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __func__,
+- sd->com_cis_ptr));
+-
+- /* Get the Card's function CIS (for each function) */
+- for (fbraddr = SDIOD_FBR_STARTADDR, func = 1;
+- func <= sd->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) {
+- sd->func_cis_ptr[func] =
+- sdioh_sdmmc_get_cisaddr(sd, SDIOD_FBR_CISPTR_0 + fbraddr);
+- sd_info(("%s: Function %d CIS Ptr = 0x%x\n", __func__, func,
+- sd->func_cis_ptr[func]));
+- }
+-
+- sd->func_cis_ptr[0] = sd->com_cis_ptr;
+- sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __func__,
+- sd->com_cis_ptr));
+-
+- /* Enable Function 1 */
+- sdio_claim_host(gInstance->func[1]);
+- err_ret = sdio_enable_func(gInstance->func[1]);
+- sdio_release_host(gInstance->func[1]);
+- if (err_ret) {
+- sd_err(("bcmsdh_sdmmc: Failed to enable F1 Err: 0x%08x",
+- err_ret));
+- }
+-
+- return false;
+-}
+-
+-/*
+- * Public entry points & extern's
+- */
+-sdioh_info_t *sdioh_attach(void *bar0, uint irq)
+-{
+- sdioh_info_t *sd;
+- int err_ret;
+-
+- sd_trace(("%s\n", __func__));
+-
+- if (gInstance == NULL) {
+- sd_err(("%s: SDIO Device not present\n", __func__));
+- return NULL;
+- }
+-
+- sd = kzalloc(sizeof(sdioh_info_t), GFP_ATOMIC);
+- if (sd == NULL) {
+- sd_err(("sdioh_attach: out of memory\n"));
+- return NULL;
+- }
+- if (sdioh_sdmmc_osinit(sd) != 0) {
+- sd_err(("%s:sdioh_sdmmc_osinit() failed\n", __func__));
+- kfree(sd);
+- return NULL;
+- }
+-
+- sd->num_funcs = 2;
+- sd->sd_blockmode = true;
+- sd->use_client_ints = true;
+- sd->client_block_size[0] = 64;
+-
+- gInstance->sd = sd;
+-
+- /* Claim host controller */
+- sdio_claim_host(gInstance->func[1]);
+-
+- sd->client_block_size[1] = 64;
+- err_ret = sdio_set_block_size(gInstance->func[1], 64);
+- if (err_ret)
+- sd_err(("bcmsdh_sdmmc: Failed to set F1 blocksize\n"));
+-
+- /* Release host controller F1 */
+- sdio_release_host(gInstance->func[1]);
+-
+- if (gInstance->func[2]) {
+- /* Claim host controller F2 */
+- sdio_claim_host(gInstance->func[2]);
+-
+- sd->client_block_size[2] = sd_f2_blocksize;
+- err_ret =
+- sdio_set_block_size(gInstance->func[2], sd_f2_blocksize);
+- if (err_ret)
+- sd_err(("bcmsdh_sdmmc: Failed to set F2 blocksize "
+- "to %d\n", sd_f2_blocksize));
+-
+- /* Release host controller F2 */
+- sdio_release_host(gInstance->func[2]);
+- }
+-
+- sdioh_sdmmc_card_enablefuncs(sd);
+-
+- sd_trace(("%s: Done\n", __func__));
+- return sd;
+-}
+-
+-extern SDIOH_API_RC sdioh_detach(sdioh_info_t *sd)
+-{
+- sd_trace(("%s\n", __func__));
+-
+- if (sd) {
+-
+- /* Disable Function 2 */
+- sdio_claim_host(gInstance->func[2]);
+- sdio_disable_func(gInstance->func[2]);
+- sdio_release_host(gInstance->func[2]);
+-
+- /* Disable Function 1 */
+- sdio_claim_host(gInstance->func[1]);
+- sdio_disable_func(gInstance->func[1]);
+- sdio_release_host(gInstance->func[1]);
+-
+- /* deregister irq */
+- sdioh_sdmmc_osfree(sd);
+-
+- kfree(sd);
+- }
+- return SDIOH_API_RC_SUCCESS;
+-}
+-
+-#if defined(OOB_INTR_ONLY) && defined(HW_OOB)
+-
+-extern SDIOH_API_RC sdioh_enable_func_intr(void)
+-{
+- u8 reg;
+- int err;
+-
+- if (gInstance->func[0]) {
+- sdio_claim_host(gInstance->func[0]);
+-
+- reg = sdio_readb(gInstance->func[0], SDIOD_CCCR_INTEN, &err);
+- if (err) {
+- sd_err(("%s: error for read SDIO_CCCR_IENx : 0x%x\n",
+- __func__, err));
+- sdio_release_host(gInstance->func[0]);
+- return SDIOH_API_RC_FAIL;
+- }
+-
+- /* Enable F1 and F2 interrupts, set master enable */
+- reg |=
+- (INTR_CTL_FUNC1_EN | INTR_CTL_FUNC2_EN |
+- INTR_CTL_MASTER_EN);
+-
+- sdio_writeb(gInstance->func[0], reg, SDIOD_CCCR_INTEN, &err);
+- sdio_release_host(gInstance->func[0]);
+-
+- if (err) {
+- sd_err(("%s: error for write SDIO_CCCR_IENx : 0x%x\n",
+- __func__, err));
+- return SDIOH_API_RC_FAIL;
+- }
+- }
+-
+- return SDIOH_API_RC_SUCCESS;
+-}
+-
+-extern SDIOH_API_RC sdioh_disable_func_intr(void)
+-{
+- u8 reg;
+- int err;
+-
+- if (gInstance->func[0]) {
+- sdio_claim_host(gInstance->func[0]);
+- reg = sdio_readb(gInstance->func[0], SDIOD_CCCR_INTEN, &err);
+- if (err) {
+- sd_err(("%s: error for read SDIO_CCCR_IENx : 0x%x\n",
+- __func__, err));
+- sdio_release_host(gInstance->func[0]);
+- return SDIOH_API_RC_FAIL;
+- }
+-
+- reg &= ~(INTR_CTL_FUNC1_EN | INTR_CTL_FUNC2_EN);
+- /* Disable master interrupt with the last function interrupt */
+- if (!(reg & 0xFE))
+- reg = 0;
+- sdio_writeb(gInstance->func[0], reg, SDIOD_CCCR_INTEN, &err);
+-
+- sdio_release_host(gInstance->func[0]);
+- if (err) {
+- sd_err(("%s: error for write SDIO_CCCR_IENx : 0x%x\n",
+- __func__, err));
+- return SDIOH_API_RC_FAIL;
+- }
+- }
+- return SDIOH_API_RC_SUCCESS;
+-}
+-#endif /* defined(OOB_INTR_ONLY) && defined(HW_OOB) */
+-
+-/* Configure callback to client when we receive client interrupt */
+-extern SDIOH_API_RC
+-sdioh_interrupt_register(sdioh_info_t *sd, sdioh_cb_fn_t fn, void *argh)
+-{
+- sd_trace(("%s: Entering\n", __func__));
+- if (fn == NULL) {
+- sd_err(("%s: interrupt handler is NULL, not registering\n",
+- __func__));
+- return SDIOH_API_RC_FAIL;
+- }
+-#if !defined(OOB_INTR_ONLY)
+- sd->intr_handler = fn;
+- sd->intr_handler_arg = argh;
+- sd->intr_handler_valid = true;
+-
+- /* register and unmask irq */
+- if (gInstance->func[2]) {
+- sdio_claim_host(gInstance->func[2]);
+- sdio_claim_irq(gInstance->func[2], IRQHandlerF2);
+- sdio_release_host(gInstance->func[2]);
+- }
+-
+- if (gInstance->func[1]) {
+- sdio_claim_host(gInstance->func[1]);
+- sdio_claim_irq(gInstance->func[1], IRQHandler);
+- sdio_release_host(gInstance->func[1]);
+- }
+-#elif defined(HW_OOB)
+- sdioh_enable_func_intr();
+-#endif /* defined(OOB_INTR_ONLY) */
+- return SDIOH_API_RC_SUCCESS;
+-}
+-
+-extern SDIOH_API_RC sdioh_interrupt_deregister(sdioh_info_t *sd)
+-{
+- sd_trace(("%s: Entering\n", __func__));
+-
+-#if !defined(OOB_INTR_ONLY)
+- if (gInstance->func[1]) {
+- /* register and unmask irq */
+- sdio_claim_host(gInstance->func[1]);
+- sdio_release_irq(gInstance->func[1]);
+- sdio_release_host(gInstance->func[1]);
+- }
+-
+- if (gInstance->func[2]) {
+- /* Claim host controller F2 */
+- sdio_claim_host(gInstance->func[2]);
+- sdio_release_irq(gInstance->func[2]);
+- /* Release host controller F2 */
+- sdio_release_host(gInstance->func[2]);
+- }
+-
+- sd->intr_handler_valid = false;
+- sd->intr_handler = NULL;
+- sd->intr_handler_arg = NULL;
+-#elif defined(HW_OOB)
+- sdioh_disable_func_intr();
+-#endif /* !defined(OOB_INTR_ONLY) */
+- return SDIOH_API_RC_SUCCESS;
+-}
+-
+-extern SDIOH_API_RC sdioh_interrupt_query(sdioh_info_t *sd, bool *onoff)
+-{
+- sd_trace(("%s: Entering\n", __func__));
+- *onoff = sd->client_intr_enabled;
+- return SDIOH_API_RC_SUCCESS;
+-}
+-
+-#if defined(DHD_DEBUG)
+-extern bool sdioh_interrupt_pending(sdioh_info_t *sd)
+-{
+- return 0;
+-}
+-#endif
+-
+-uint sdioh_query_iofnum(sdioh_info_t *sd)
+-{
+- return sd->num_funcs;
+-}
+-
+-/* IOVar table */
+-enum {
+- IOV_MSGLEVEL = 1,
+- IOV_BLOCKMODE,
+- IOV_BLOCKSIZE,
+- IOV_DMA,
+- IOV_USEINTS,
+- IOV_NUMINTS,
+- IOV_NUMLOCALINTS,
+- IOV_HOSTREG,
+- IOV_DEVREG,
+- IOV_DIVISOR,
+- IOV_SDMODE,
+- IOV_HISPEED,
+- IOV_HCIREGS,
+- IOV_POWER,
+- IOV_CLOCK,
+- IOV_RXCHAIN
+-};
+-
+-const bcm_iovar_t sdioh_iovars[] = {
+- {"sd_msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0},
+- {"sd_blockmode", IOV_BLOCKMODE, 0, IOVT_BOOL, 0},
+- {"sd_blocksize", IOV_BLOCKSIZE, 0, IOVT_UINT32, 0},/* ((fn << 16) |
+- size) */
+- {"sd_dma", IOV_DMA, 0, IOVT_BOOL, 0},
+- {"sd_ints", IOV_USEINTS, 0, IOVT_BOOL, 0},
+- {"sd_numints", IOV_NUMINTS, 0, IOVT_UINT32, 0},
+- {"sd_numlocalints", IOV_NUMLOCALINTS, 0, IOVT_UINT32, 0},
+- {"sd_hostreg", IOV_HOSTREG, 0, IOVT_BUFFER, sizeof(sdreg_t)}
+- ,
+- {"sd_devreg", IOV_DEVREG, 0, IOVT_BUFFER, sizeof(sdreg_t)}
+- ,
+- {"sd_divisor", IOV_DIVISOR, 0, IOVT_UINT32, 0}
+- ,
+- {"sd_power", IOV_POWER, 0, IOVT_UINT32, 0}
+- ,
+- {"sd_clock", IOV_CLOCK, 0, IOVT_UINT32, 0}
+- ,
+- {"sd_mode", IOV_SDMODE, 0, IOVT_UINT32, 100}
+- ,
+- {"sd_highspeed", IOV_HISPEED, 0, IOVT_UINT32, 0}
+- ,
+- {"sd_rxchain", IOV_RXCHAIN, 0, IOVT_BOOL, 0}
+- ,
+- {NULL, 0, 0, 0, 0}
+-};
+-
+-int
+-sdioh_iovar_op(sdioh_info_t *si, const char *name,
+- void *params, int plen, void *arg, int len, bool set)
+-{
+- const bcm_iovar_t *vi = NULL;
+- int bcmerror = 0;
+- int val_size;
+- s32 int_val = 0;
+- bool bool_val;
+- u32 actionid;
+-
+- ASSERT(name);
+- ASSERT(len >= 0);
+-
+- /* Get must have return space; Set does not take qualifiers */
+- ASSERT(set || (arg && len));
+- ASSERT(!set || (!params && !plen));
+-
+- sd_trace(("%s: Enter (%s %s)\n", __func__, (set ? "set" : "get"),
+- name));
+-
+- vi = bcm_iovar_lookup(sdioh_iovars, name);
+- if (vi == NULL) {
+- bcmerror = -ENOTSUPP;
+- goto exit;
+- }
+-
+- bcmerror = bcm_iovar_lencheck(vi, arg, len, set);
+- if (bcmerror != 0)
+- goto exit;
+-
+- /* Set up params so get and set can share the convenience variables */
+- if (params == NULL) {
+- params = arg;
+- plen = len;
+- }
+-
+- if (vi->type == IOVT_VOID)
+- val_size = 0;
+- else if (vi->type == IOVT_BUFFER)
+- val_size = len;
+- else
+- val_size = sizeof(int);
+-
+- if (plen >= (int)sizeof(int_val))
+- memcpy(&int_val, params, sizeof(int_val));
+-
+- bool_val = (int_val != 0) ? true : false;
+-
+- actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
+- switch (actionid) {
+- case IOV_GVAL(IOV_MSGLEVEL):
+- int_val = (s32) sd_msglevel;
+- memcpy(arg, &int_val, val_size);
+- break;
+-
+- case IOV_SVAL(IOV_MSGLEVEL):
+- sd_msglevel = int_val;
+- break;
+-
+- case IOV_GVAL(IOV_BLOCKMODE):
+- int_val = (s32) si->sd_blockmode;
+- memcpy(arg, &int_val, val_size);
+- break;
+-
+- case IOV_SVAL(IOV_BLOCKMODE):
+- si->sd_blockmode = (bool) int_val;
+- /* Haven't figured out how to make non-block mode with DMA */
+- break;
+-
+- case IOV_GVAL(IOV_BLOCKSIZE):
+- if ((u32) int_val > si->num_funcs) {
+- bcmerror = -EINVAL;
+- break;
+- }
+- int_val = (s32) si->client_block_size[int_val];
+- memcpy(arg, &int_val, val_size);
+- break;
+-
+- case IOV_SVAL(IOV_BLOCKSIZE):
+- {
+- uint func = ((u32) int_val >> 16);
+- uint blksize = (u16) int_val;
+- uint maxsize;
+-
+- if (func > si->num_funcs) {
+- bcmerror = -EINVAL;
+- break;
+- }
+-
+- switch (func) {
+- case 0:
+- maxsize = 32;
+- break;
+- case 1:
+- maxsize = BLOCK_SIZE_4318;
+- break;
+- case 2:
+- maxsize = BLOCK_SIZE_4328;
+- break;
+- default:
+- maxsize = 0;
+- }
+- if (blksize > maxsize) {
+- bcmerror = -EINVAL;
+- break;
+- }
+- if (!blksize)
+- blksize = maxsize;
+-
+- /* Now set it */
+- si->client_block_size[func] = blksize;
+-
+- break;
+- }
+-
+- case IOV_GVAL(IOV_RXCHAIN):
+- int_val = false;
+- memcpy(arg, &int_val, val_size);
+- break;
+-
+- case IOV_GVAL(IOV_DMA):
+- int_val = (s32) si->sd_use_dma;
+- memcpy(arg, &int_val, val_size);
+- break;
+-
+- case IOV_SVAL(IOV_DMA):
+- si->sd_use_dma = (bool) int_val;
+- break;
+-
+- case IOV_GVAL(IOV_USEINTS):
+- int_val = (s32) si->use_client_ints;
+- memcpy(arg, &int_val, val_size);
+- break;
+-
+- case IOV_SVAL(IOV_USEINTS):
+- si->use_client_ints = (bool) int_val;
+- if (si->use_client_ints)
+- si->intmask |= CLIENT_INTR;
+- else
+- si->intmask &= ~CLIENT_INTR;
+-
+- break;
+-
+- case IOV_GVAL(IOV_DIVISOR):
+- int_val = (u32) sd_divisor;
+- memcpy(arg, &int_val, val_size);
+- break;
+-
+- case IOV_SVAL(IOV_DIVISOR):
+- sd_divisor = int_val;
+- break;
+-
+- case IOV_GVAL(IOV_POWER):
+- int_val = (u32) sd_power;
+- memcpy(arg, &int_val, val_size);
+- break;
+-
+- case IOV_SVAL(IOV_POWER):
+- sd_power = int_val;
+- break;
+-
+- case IOV_GVAL(IOV_CLOCK):
+- int_val = (u32) sd_clock;
+- memcpy(arg, &int_val, val_size);
+- break;
+-
+- case IOV_SVAL(IOV_CLOCK):
+- sd_clock = int_val;
+- break;
+-
+- case IOV_GVAL(IOV_SDMODE):
+- int_val = (u32) sd_sdmode;
+- memcpy(arg, &int_val, val_size);
+- break;
+-
+- case IOV_SVAL(IOV_SDMODE):
+- sd_sdmode = int_val;
+- break;
+-
+- case IOV_GVAL(IOV_HISPEED):
+- int_val = (u32) sd_hiok;
+- memcpy(arg, &int_val, val_size);
+- break;
+-
+- case IOV_SVAL(IOV_HISPEED):
+- sd_hiok = int_val;
+- break;
+-
+- case IOV_GVAL(IOV_NUMINTS):
+- int_val = (s32) si->intrcount;
+- memcpy(arg, &int_val, val_size);
+- break;
+-
+- case IOV_GVAL(IOV_NUMLOCALINTS):
+- int_val = (s32) 0;
+- memcpy(arg, &int_val, val_size);
+- break;
+-
+- case IOV_GVAL(IOV_HOSTREG):
+- {
+- sdreg_t *sd_ptr = (sdreg_t *) params;
+-
+- if (sd_ptr->offset < SD_SysAddr
+- || sd_ptr->offset > SD_MaxCurCap) {
+- sd_err(("%s: bad offset 0x%x\n", __func__,
+- sd_ptr->offset));
+- bcmerror = -EINVAL;
+- break;
+- }
+-
+- sd_trace(("%s: rreg%d at offset %d\n", __func__,
+- (sd_ptr->offset & 1) ? 8
+- : ((sd_ptr->offset & 2) ? 16 : 32),
+- sd_ptr->offset));
+- if (sd_ptr->offset & 1)
+- int_val = 8; /* sdioh_sdmmc_rreg8(si,
+- sd_ptr->offset); */
+- else if (sd_ptr->offset & 2)
+- int_val = 16; /* sdioh_sdmmc_rreg16(si,
+- sd_ptr->offset); */
+- else
+- int_val = 32; /* sdioh_sdmmc_rreg(si,
+- sd_ptr->offset); */
+-
+- memcpy(arg, &int_val, sizeof(int_val));
+- break;
+- }
+-
+- case IOV_SVAL(IOV_HOSTREG):
+- {
+- sdreg_t *sd_ptr = (sdreg_t *) params;
+-
+- if (sd_ptr->offset < SD_SysAddr
+- || sd_ptr->offset > SD_MaxCurCap) {
+- sd_err(("%s: bad offset 0x%x\n", __func__,
+- sd_ptr->offset));
+- bcmerror = -EINVAL;
+- break;
+- }
+-
+- sd_trace(("%s: wreg%d value 0x%08x at offset %d\n",
+- __func__, sd_ptr->value,
+- (sd_ptr->offset & 1) ? 8
+- : ((sd_ptr->offset & 2) ? 16 : 32),
+- sd_ptr->offset));
+- break;
+- }
+-
+- case IOV_GVAL(IOV_DEVREG):
+- {
+- sdreg_t *sd_ptr = (sdreg_t *) params;
+- u8 data = 0;
+-
+- if (sdioh_cfg_read
+- (si, sd_ptr->func, sd_ptr->offset, &data)) {
+- bcmerror = -EIO;
+- break;
+- }
+-
+- int_val = (int)data;
+- memcpy(arg, &int_val, sizeof(int_val));
+- break;
+- }
+-
+- case IOV_SVAL(IOV_DEVREG):
+- {
+- sdreg_t *sd_ptr = (sdreg_t *) params;
+- u8 data = (u8) sd_ptr->value;
+-
+- if (sdioh_cfg_write
+- (si, sd_ptr->func, sd_ptr->offset, &data)) {
+- bcmerror = -EIO;
+- break;
+- }
+- break;
+- }
+-
+- default:
+- bcmerror = -ENOTSUPP;
+- break;
+- }
+-exit:
+-
+- return bcmerror;
+-}
+-
+-#if defined(OOB_INTR_ONLY) && defined(HW_OOB)
+-
+-SDIOH_API_RC sdioh_enable_hw_oob_intr(sdioh_info_t *sd, bool enable)
+-{
+- SDIOH_API_RC status;
+- u8 data;
+-
+- if (enable)
+- data = 3; /* enable hw oob interrupt */
+- else
+- data = 4; /* disable hw oob interrupt */
+- data |= 4; /* Active HIGH */
+-
+- status = sdioh_request_byte(sd, SDIOH_WRITE, 0, 0xf2, &data);
+- return status;
+-}
+-#endif /* defined(OOB_INTR_ONLY) && defined(HW_OOB) */
+-
+-extern SDIOH_API_RC
+-sdioh_cfg_read(sdioh_info_t *sd, uint fnc_num, u32 addr, u8 *data)
+-{
+- SDIOH_API_RC status;
+- /* No lock needed since sdioh_request_byte does locking */
+- status = sdioh_request_byte(sd, SDIOH_READ, fnc_num, addr, data);
+- return status;
+-}
+-
+-extern SDIOH_API_RC
+-sdioh_cfg_write(sdioh_info_t *sd, uint fnc_num, u32 addr, u8 *data)
+-{
+- /* No lock needed since sdioh_request_byte does locking */
+- SDIOH_API_RC status;
+- status = sdioh_request_byte(sd, SDIOH_WRITE, fnc_num, addr, data);
+- return status;
+-}
+-
+-static int sdioh_sdmmc_get_cisaddr(sdioh_info_t *sd, u32 regaddr)
+-{
+- /* read 24 bits and return valid 17 bit addr */
+- int i;
+- u32 scratch, regdata;
+- u8 *ptr = (u8 *)&scratch;
+- for (i = 0; i < 3; i++) {
+- if ((sdioh_sdmmc_card_regread(sd, 0, regaddr, 1, ®data)) !=
+- SUCCESS)
+- sd_err(("%s: Can't read!\n", __func__));
+-
+- *ptr++ = (u8) regdata;
+- regaddr++;
+- }
+-
+- /* Only the lower 17-bits are valid */
+- scratch = le32_to_cpu(scratch);
+- scratch &= 0x0001FFFF;
+- return scratch;
+-}
+-
+-extern SDIOH_API_RC
+-sdioh_cis_read(sdioh_info_t *sd, uint func, u8 *cisd, u32 length)
+-{
+- u32 count;
+- int offset;
+- u32 foo;
+- u8 *cis = cisd;
+-
+- sd_trace(("%s: Func = %d\n", __func__, func));
+-
+- if (!sd->func_cis_ptr[func]) {
+- memset(cis, 0, length);
+- sd_err(("%s: no func_cis_ptr[%d]\n", __func__, func));
+- return SDIOH_API_RC_FAIL;
+- }
+-
+- sd_err(("%s: func_cis_ptr[%d]=0x%04x\n", __func__, func,
+- sd->func_cis_ptr[func]));
+-
+- for (count = 0; count < length; count++) {
+- offset = sd->func_cis_ptr[func] + count;
+- if (sdioh_sdmmc_card_regread(sd, 0, offset, 1, &foo) < 0) {
+- sd_err(("%s: regread failed: Can't read CIS\n",
+- __func__));
+- return SDIOH_API_RC_FAIL;
+- }
+-
+- *cis = (u8) (foo & 0xff);
+- cis++;
+- }
+-
+- return SDIOH_API_RC_SUCCESS;
+-}
+-
+-extern SDIOH_API_RC
+-sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr,
+- u8 *byte)
+-{
+- int err_ret;
+-
+- sd_info(("%s: rw=%d, func=%d, addr=0x%05x\n", __func__, rw, func,
+- regaddr));
+-
+- DHD_PM_RESUME_WAIT(sdioh_request_byte_wait);
+- DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
+- if (rw) { /* CMD52 Write */
+- if (func == 0) {
+- /* Can only directly write to some F0 registers.
+- * Handle F2 enable
+- * as a special case.
+- */
+- if (regaddr == SDIOD_CCCR_IOEN) {
+- if (gInstance->func[2]) {
+- sdio_claim_host(gInstance->func[2]);
+- if (*byte & SDIO_FUNC_ENABLE_2) {
+- /* Enable Function 2 */
+- err_ret =
+- sdio_enable_func
+- (gInstance->func[2]);
+- if (err_ret)
+- sd_err(("bcmsdh_sdmmc: enable F2 failed:%d",
+- err_ret));
+- } else {
+- /* Disable Function 2 */
+- err_ret =
+- sdio_disable_func
+- (gInstance->func[2]);
+- if (err_ret)
+- sd_err(("bcmsdh_sdmmc: Disab F2 failed:%d",
+- err_ret));
+- }
+- sdio_release_host(gInstance->func[2]);
+- }
+- }
+-#if defined(MMC_SDIO_ABORT)
+- /* to allow abort command through F1 */
+- else if (regaddr == SDIOD_CCCR_IOABORT) {
+- sdio_claim_host(gInstance->func[func]);
+- /*
+- * this sdio_f0_writeb() can be replaced
+- * with another api
+- * depending upon MMC driver change.
+- * As of this time, this is temporaray one
+- */
+- sdio_writeb(gInstance->func[func], *byte,
+- regaddr, &err_ret);
+- sdio_release_host(gInstance->func[func]);
+- }
+-#endif /* MMC_SDIO_ABORT */
+- else if (regaddr < 0xF0) {
+- sd_err(("bcmsdh_sdmmc: F0 Wr:0x%02x: write "
+- "disallowed\n", regaddr));
+- } else {
+- /* Claim host controller, perform F0 write,
+- and release */
+- sdio_claim_host(gInstance->func[func]);
+- sdio_f0_writeb(gInstance->func[func], *byte,
+- regaddr, &err_ret);
+- sdio_release_host(gInstance->func[func]);
+- }
+- } else {
+- /* Claim host controller, perform Fn write,
+- and release */
+- sdio_claim_host(gInstance->func[func]);
+- sdio_writeb(gInstance->func[func], *byte, regaddr,
+- &err_ret);
+- sdio_release_host(gInstance->func[func]);
+- }
+- } else { /* CMD52 Read */
+- /* Claim host controller, perform Fn read, and release */
+- sdio_claim_host(gInstance->func[func]);
+-
+- if (func == 0) {
+- *byte =
+- sdio_f0_readb(gInstance->func[func], regaddr,
+- &err_ret);
+- } else {
+- *byte =
+- sdio_readb(gInstance->func[func], regaddr,
+- &err_ret);
+- }
+-
+- sdio_release_host(gInstance->func[func]);
+- }
+-
+- if (err_ret)
+- sd_err(("bcmsdh_sdmmc: Failed to %s byte F%d:@0x%05x=%02x, "
+- "Err: %d\n", rw ? "Write" : "Read", func, regaddr,
+- *byte, err_ret));
+-
+- return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
+-}
+-
+-extern SDIOH_API_RC
+-sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func,
+- uint addr, u32 *word, uint nbytes)
+-{
+- int err_ret = SDIOH_API_RC_FAIL;
+-
+- if (func == 0) {
+- sd_err(("%s: Only CMD52 allowed to F0.\n", __func__));
+- return SDIOH_API_RC_FAIL;
+- }
+-
+- sd_info(("%s: cmd_type=%d, rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
+- __func__, cmd_type, rw, func, addr, nbytes));
+-
+- DHD_PM_RESUME_WAIT(sdioh_request_word_wait);
+- DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
+- /* Claim host controller */
+- sdio_claim_host(gInstance->func[func]);
+-
+- if (rw) { /* CMD52 Write */
+- if (nbytes == 4) {
+- sdio_writel(gInstance->func[func], *word, addr,
+- &err_ret);
+- } else if (nbytes == 2) {
+- sdio_writew(gInstance->func[func], (*word & 0xFFFF),
+- addr, &err_ret);
+- } else {
+- sd_err(("%s: Invalid nbytes: %d\n", __func__, nbytes));
+- }
+- } else { /* CMD52 Read */
+- if (nbytes == 4) {
+- *word =
+- sdio_readl(gInstance->func[func], addr, &err_ret);
+- } else if (nbytes == 2) {
+- *word =
+- sdio_readw(gInstance->func[func], addr,
+- &err_ret) & 0xFFFF;
+- } else {
+- sd_err(("%s: Invalid nbytes: %d\n", __func__, nbytes));
+- }
+- }
+-
+- /* Release host controller */
+- sdio_release_host(gInstance->func[func]);
+-
+- if (err_ret) {
+- sd_err(("bcmsdh_sdmmc: Failed to %s word, Err: 0x%08x",
+- rw ? "Write" : "Read", err_ret));
+- }
+-
+- return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
+-}
+-
+-static SDIOH_API_RC
+-sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func,
+- uint addr, struct sk_buff *pkt)
+-{
+- bool fifo = (fix_inc == SDIOH_DATA_FIX);
+- u32 SGCount = 0;
+- int err_ret = 0;
+-
+- struct sk_buff *pnext;
+-
+- sd_trace(("%s: Enter\n", __func__));
+-
+- ASSERT(pkt);
+- DHD_PM_RESUME_WAIT(sdioh_request_packet_wait);
+- DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
+-
+- /* Claim host controller */
+- sdio_claim_host(gInstance->func[func]);
+- for (pnext = pkt; pnext; pnext = pnext->next) {
+- uint pkt_len = pnext->len;
+- pkt_len += 3;
+- pkt_len &= 0xFFFFFFFC;
+-
+-#ifdef CONFIG_MMC_MSM7X00A
+- if ((pkt_len % 64) == 32) {
+- sd_trace(("%s: Rounding up TX packet +=32\n",
+- __func__));
+- pkt_len += 32;
+- }
+-#endif /* CONFIG_MMC_MSM7X00A */
+- /* Make sure the packet is aligned properly.
+- * If it isn't, then this
+- * is the fault of sdioh_request_buffer() which
+- * is supposed to give
+- * us something we can work with.
+- */
+- ASSERT(((u32) (pkt->data) & DMA_ALIGN_MASK) == 0);
+-
+- if ((write) && (!fifo)) {
+- err_ret = sdio_memcpy_toio(gInstance->func[func], addr,
+- ((u8 *) (pnext->data)),
+- pkt_len);
+- } else if (write) {
+- err_ret = sdio_memcpy_toio(gInstance->func[func], addr,
+- ((u8 *) (pnext->data)),
+- pkt_len);
+- } else if (fifo) {
+- err_ret = sdio_readsb(gInstance->func[func],
+- ((u8 *) (pnext->data)),
+- addr, pkt_len);
+- } else {
+- err_ret = sdio_memcpy_fromio(gInstance->func[func],
+- ((u8 *) (pnext->data)),
+- addr, pkt_len);
+- }
+-
+- if (err_ret) {
+- sd_err(("%s: %s FAILED %p[%d], addr=0x%05x, pkt_len=%d,"
+- "ERR=0x%08x\n", __func__,
+- (write) ? "TX" : "RX",
+- pnext, SGCount, addr, pkt_len, err_ret));
+- } else {
+- sd_trace(("%s: %s xfr'd %p[%d], addr=0x%05x, len=%d\n",
+- __func__,
+- (write) ? "TX" : "RX",
+- pnext, SGCount, addr, pkt_len));
+- }
+-
+- if (!fifo)
+- addr += pkt_len;
+- SGCount++;
+-
+- }
+-
+- /* Release host controller */
+- sdio_release_host(gInstance->func[func]);
+-
+- sd_trace(("%s: Exit\n", __func__));
+- return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
+-}
+-
+-/*
+- * This function takes a buffer or packet, and fixes everything up
+- * so that in the end, a DMA-able packet is created.
+- *
+- * A buffer does not have an associated packet pointer,
+- * and may or may not be aligned.
+- * A packet may consist of a single packet, or a packet chain.
+- * If it is a packet chain, then all the packets in the chain
+- * must be properly aligned.
+- *
+- * If the packet data is not aligned, then there may only be
+- * one packet, and in this case, it is copied to a new
+- * aligned packet.
+- *
+- */
+-extern SDIOH_API_RC
+-sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write,
+- uint func, uint addr, uint reg_width, uint buflen_u,
+- u8 *buffer, struct sk_buff *pkt)
+-{
+- SDIOH_API_RC Status;
+- struct sk_buff *mypkt = NULL;
+-
+- sd_trace(("%s: Enter\n", __func__));
+-
+- DHD_PM_RESUME_WAIT(sdioh_request_buffer_wait);
+- DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
+- /* Case 1: we don't have a packet. */
+- if (pkt == NULL) {
+- sd_data(("%s: Creating new %s Packet, len=%d\n",
+- __func__, write ? "TX" : "RX", buflen_u));
+- mypkt = bcm_pkt_buf_get_skb(buflen_u);
+- if (!mypkt) {
+- sd_err(("%s: bcm_pkt_buf_get_skb failed: len %d\n",
+- __func__, buflen_u));
+- return SDIOH_API_RC_FAIL;
+- }
+-
+- /* For a write, copy the buffer data into the packet. */
+- if (write)
+- memcpy(mypkt->data, buffer, buflen_u);
+-
+- Status =
+- sdioh_request_packet(sd, fix_inc, write, func, addr, mypkt);
+-
+- /* For a read, copy the packet data back to the buffer. */
+- if (!write)
+- memcpy(buffer, mypkt->data, buflen_u);
+-
+- bcm_pkt_buf_free_skb(mypkt);
+- } else if (((u32) (pkt->data) & DMA_ALIGN_MASK) != 0) {
+- /* Case 2: We have a packet, but it is unaligned. */
+-
+- /* In this case, we cannot have a chain. */
+- ASSERT(pkt->next == NULL);
+-
+- sd_data(("%s: Creating aligned %s Packet, len=%d\n",
+- __func__, write ? "TX" : "RX", pkt->len));
+- mypkt = bcm_pkt_buf_get_skb(pkt->len);
+- if (!mypkt) {
+- sd_err(("%s: bcm_pkt_buf_get_skb failed: len %d\n",
+- __func__, pkt->len));
+- return SDIOH_API_RC_FAIL;
+- }
+-
+- /* For a write, copy the buffer data into the packet. */
+- if (write)
+- memcpy(mypkt->data, pkt->data, pkt->len);
+-
+- Status =
+- sdioh_request_packet(sd, fix_inc, write, func, addr, mypkt);
+-
+- /* For a read, copy the packet data back to the buffer. */
+- if (!write)
+- memcpy(pkt->data, mypkt->data, mypkt->len);
+-
+- bcm_pkt_buf_free_skb(mypkt);
+- } else { /* case 3: We have a packet and
+- it is aligned. */
+- sd_data(("%s: Aligned %s Packet, direct DMA\n",
+- __func__, write ? "Tx" : "Rx"));
+- Status =
+- sdioh_request_packet(sd, fix_inc, write, func, addr, pkt);
+- }
+-
+- return Status;
+-}
+-
+-/* this function performs "abort" for both of host & device */
+-extern int sdioh_abort(sdioh_info_t *sd, uint func)
+-{
+-#if defined(MMC_SDIO_ABORT)
+- char t_func = (char)func;
+-#endif /* defined(MMC_SDIO_ABORT) */
+- sd_trace(("%s: Enter\n", __func__));
+-
+-#if defined(MMC_SDIO_ABORT)
+- /* issue abort cmd52 command through F1 */
+- sdioh_request_byte(sd, SD_IO_OP_WRITE, SDIO_FUNC_0, SDIOD_CCCR_IOABORT,
+- &t_func);
+-#endif /* defined(MMC_SDIO_ABORT) */
+-
+- sd_trace(("%s: Exit\n", __func__));
+- return SDIOH_API_RC_SUCCESS;
+-}
+-
+-/* Reset and re-initialize the device */
+-int sdioh_sdio_reset(sdioh_info_t *si)
+-{
+- sd_trace(("%s: Enter\n", __func__));
+- sd_trace(("%s: Exit\n", __func__));
+- return SDIOH_API_RC_SUCCESS;
+-}
+-
+-/* Disable device interrupt */
+-void sdioh_sdmmc_devintr_off(sdioh_info_t *sd)
+-{
+- sd_trace(("%s: %d\n", __func__, sd->use_client_ints));
+- sd->intmask &= ~CLIENT_INTR;
+-}
+-
+-/* Enable device interrupt */
+-void sdioh_sdmmc_devintr_on(sdioh_info_t *sd)
+-{
+- sd_trace(("%s: %d\n", __func__, sd->use_client_ints));
+- sd->intmask |= CLIENT_INTR;
+-}
+-
+-/* Read client card reg */
+-int
+-sdioh_sdmmc_card_regread(sdioh_info_t *sd, int func, u32 regaddr,
+- int regsize, u32 *data)
+-{
+-
+- if ((func == 0) || (regsize == 1)) {
+- u8 temp = 0;
+-
+- sdioh_request_byte(sd, SDIOH_READ, func, regaddr, &temp);
+- *data = temp;
+- *data &= 0xff;
+- sd_data(("%s: byte read data=0x%02x\n", __func__, *data));
+- } else {
+- sdioh_request_word(sd, 0, SDIOH_READ, func, regaddr, data,
+- regsize);
+- if (regsize == 2)
+- *data &= 0xffff;
+-
+- sd_data(("%s: word read data=0x%08x\n", __func__, *data));
+- }
+-
+- return SUCCESS;
+-}
+-
+-#if !defined(OOB_INTR_ONLY)
+-/* bcmsdh_sdmmc interrupt handler */
+-static void IRQHandler(struct sdio_func *func)
+-{
+- sdioh_info_t *sd;
+-
+- sd_trace(("bcmsdh_sdmmc: ***IRQHandler\n"));
+- sd = gInstance->sd;
+-
+- ASSERT(sd != NULL);
+- sdio_release_host(gInstance->func[0]);
+-
+- if (sd->use_client_ints) {
+- sd->intrcount++;
+- ASSERT(sd->intr_handler);
+- ASSERT(sd->intr_handler_arg);
+- (sd->intr_handler) (sd->intr_handler_arg);
+- } else {
+- sd_err(("bcmsdh_sdmmc: ***IRQHandler\n"));
+-
+- sd_err(("%s: Not ready for intr: enabled %d, handler %p\n",
+- __func__, sd->client_intr_enabled, sd->intr_handler));
+- }
+-
+- sdio_claim_host(gInstance->func[0]);
+-}
+-
+-/* bcmsdh_sdmmc interrupt handler for F2 (dummy handler) */
+-static void IRQHandlerF2(struct sdio_func *func)
+-{
+- sdioh_info_t *sd;
+-
+- sd_trace(("bcmsdh_sdmmc: ***IRQHandlerF2\n"));
+-
+- sd = gInstance->sd;
+-
+- ASSERT(sd != NULL);
+-}
+-#endif /* !defined(OOB_INTR_ONLY) */
+-
+-#ifdef NOTUSED
+-/* Write client card reg */
+-static int
+-sdioh_sdmmc_card_regwrite(sdioh_info_t *sd, int func, u32 regaddr,
+- int regsize, u32 data)
+-{
+-
+- if ((func == 0) || (regsize == 1)) {
+- u8 temp;
+-
+- temp = data & 0xff;
+- sdioh_request_byte(sd, SDIOH_READ, func, regaddr, &temp);
+- sd_data(("%s: byte write data=0x%02x\n", __func__, data));
+- } else {
+- if (regsize == 2)
+- data &= 0xffff;
+-
+- sdioh_request_word(sd, 0, SDIOH_READ, func, regaddr, &data,
+- regsize);
+-
+- sd_data(("%s: word write data=0x%08x\n", __func__, data));
+- }
+-
+- return SUCCESS;
+-}
+-#endif /* NOTUSED */
+-
+-int sdioh_start(sdioh_info_t *si, int stage)
+-{
+- return 0;
+-}
+-
+-int sdioh_stop(sdioh_info_t *si)
+-{
+- return 0;
+-}
+diff --git a/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.h b/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.h
+deleted file mode 100644
+index 3ef42b3..0000000
+--- a/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.h
++++ /dev/null
+@@ -1,134 +0,0 @@
+-/*
+- * Copyright (c) 2010 Broadcom Corporation
+- *
+- * 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 __BCMSDH_SDMMC_H__
+-#define __BCMSDH_SDMMC_H__
+-
+-#ifdef BCMDBG
+-#define sd_err(x) \
+- do { \
+- if ((sd_msglevel & SDH_ERROR_VAL) && net_ratelimit()) \
+- printk x; \
+- } while (0)
+-#define sd_trace(x) \
+- do { \
+- if ((sd_msglevel & SDH_TRACE_VAL) && net_ratelimit()) \
+- printk x; \
+- } while (0)
+-#define sd_info(x) \
+- do { \
+- if ((sd_msglevel & SDH_INFO_VAL) && net_ratelimit()) \
+- printk x; \
+- } while (0)
+-#define sd_debug(x) \
+- do { \
+- if ((sd_msglevel & SDH_DEBUG_VAL) && net_ratelimit()) \
+- printk x; \
+- } while (0)
+-#define sd_data(x) \
+- do { \
+- if ((sd_msglevel & SDH_DATA_VAL) && net_ratelimit()) \
+- printk x; \
+- } while (0)
+-#define sd_ctrl(x) \
+- do { \
+- if ((sd_msglevel & SDH_CTRL_VAL) && net_ratelimit()) \
+- printk x; \
+- } while (0)
+-#else
+-#define sd_err(x)
+-#define sd_trace(x)
+-#define sd_info(x)
+-#define sd_debug(x)
+-#define sd_data(x)
+-#define sd_ctrl(x)
+-#endif
+-
+-/* Allocate/init/free per-OS private data */
+-extern int sdioh_sdmmc_osinit(sdioh_info_t *sd);
+-extern void sdioh_sdmmc_osfree(sdioh_info_t *sd);
+-
+-#define BLOCK_SIZE_64 64
+-#define BLOCK_SIZE_512 512
+-#define BLOCK_SIZE_4318 64
+-#define BLOCK_SIZE_4328 512
+-
+-/* internal return code */
+-#define SUCCESS 0
+-#define ERROR 1
+-
+-/* private bus modes */
+-#define SDIOH_MODE_SD4 2
+-#define CLIENT_INTR 0x100 /* Get rid of this! */
+-
+-struct sdioh_info {
+- struct osl_info *osh; /* osh handler */
+- bool client_intr_enabled; /* interrupt connnected flag */
+- bool intr_handler_valid; /* client driver interrupt handler valid */
+- sdioh_cb_fn_t intr_handler; /* registered interrupt handler */
+- void *intr_handler_arg; /* argument to call interrupt handler */
+- u16 intmask; /* Current active interrupts */
+- void *sdos_info; /* Pointer to per-OS private data */
+-
+- uint irq; /* Client irq */
+- int intrcount; /* Client interrupts */
+- bool sd_use_dma; /* DMA on CMD53 */
+- bool sd_blockmode; /* sd_blockmode == false => 64 Byte Cmd 53s. */
+- /* Must be on for sd_multiblock to be effective */
+- bool use_client_ints; /* If this is false, make sure to restore */
+- int sd_mode; /* SD1/SD4/SPI */
+- int client_block_size[SDIOD_MAX_IOFUNCS]; /* Blocksize */
+- u8 num_funcs; /* Supported funcs on client */
+- u32 com_cis_ptr;
+- u32 func_cis_ptr[SDIOD_MAX_IOFUNCS];
+- uint max_dma_len;
+- uint max_dma_descriptors; /* DMA Descriptors supported by this controller. */
+- /* SDDMA_DESCRIPTOR SGList[32]; *//* Scatter/Gather DMA List */
+-};
+-
+-/************************************************************
+- * Internal interfaces: per-port references into bcmsdh_sdmmc.c
+- */
+-
+-/* Global message bits */
+-extern uint sd_msglevel;
+-
+-/* OS-independent interrupt handler */
+-extern bool check_client_intr(sdioh_info_t *sd);
+-
+-/* Core interrupt enable/disable of device interrupts */
+-extern void sdioh_sdmmc_devintr_on(sdioh_info_t *sd);
+-extern void sdioh_sdmmc_devintr_off(sdioh_info_t *sd);
+-
+-/**************************************************************
+- * Internal interfaces: bcmsdh_sdmmc.c references to per-port code
+- */
+-
+-/* Register mapping routines */
+-extern u32 *sdioh_sdmmc_reg_map(s32 addr, int size);
+-extern void sdioh_sdmmc_reg_unmap(s32 addr, int size);
+-
+-/* Interrupt (de)registration routines */
+-extern int sdioh_sdmmc_register_irq(sdioh_info_t *sd, uint irq);
+-extern void sdioh_sdmmc_free_irq(uint irq, sdioh_info_t *sd);
+-
+-typedef struct _BCMSDH_SDMMC_INSTANCE {
+- sdioh_info_t *sd;
+- struct sdio_func *func[SDIOD_MAX_IOFUNCS];
+- u32 host_claimed;
+-} BCMSDH_SDMMC_INSTANCE, *PBCMSDH_SDMMC_INSTANCE;
+-
+-#endif /* __BCMSDH_SDMMC_H__ */
+diff --git a/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc_linux.c b/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc_linux.c
+deleted file mode 100644
+index 2792a4d..0000000
+--- a/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc_linux.c
++++ /dev/null
+@@ -1,235 +0,0 @@
+-/*
+- * Copyright (c) 2010 Broadcom Corporation
+- *
+- * 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/types.h>
+-#include <linux/sched.h> /* request_irq() */
+-#include <linux/netdevice.h>
+-#include <bcmdefs.h>
+-#include <bcmutils.h>
+-#include <sdio.h> /* SDIO Specs */
+-#include <bcmsdbus.h> /* bcmsdh to/from specific controller APIs */
+-#include <sdiovar.h> /* to get msglevel bit values */
+-
+-#include <linux/mmc/core.h>
+-#include <linux/mmc/card.h>
+-#include <linux/mmc/sdio_func.h>
+-#include <linux/mmc/sdio_ids.h>
+-
+-#include "dngl_stats.h"
+-#include "dhd.h"
+-
+-#if !defined(SDIO_VENDOR_ID_BROADCOM)
+-#define SDIO_VENDOR_ID_BROADCOM 0x02d0
+-#endif /* !defined(SDIO_VENDOR_ID_BROADCOM) */
+-
+-#define SDIO_DEVICE_ID_BROADCOM_DEFAULT 0x0000
+-
+-#if !defined(SDIO_DEVICE_ID_BROADCOM_4325_SDGWB)
+-#define SDIO_DEVICE_ID_BROADCOM_4325_SDGWB 0x0492 /* BCM94325SDGWB */
+-#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4325_SDGWB) */
+-#if !defined(SDIO_DEVICE_ID_BROADCOM_4325)
+-#define SDIO_DEVICE_ID_BROADCOM_4325 0x0493
+-#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4325) */
+-#if !defined(SDIO_DEVICE_ID_BROADCOM_4329)
+-#define SDIO_DEVICE_ID_BROADCOM_4329 0x4329
+-#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4329) */
+-#if !defined(SDIO_DEVICE_ID_BROADCOM_4319)
+-#define SDIO_DEVICE_ID_BROADCOM_4319 0x4319
+-#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4329) */
+-
+-#include <bcmsdh_sdmmc.h>
+-
+-#include <dhd_dbg.h>
+-#include <wl_cfg80211.h>
+-
+-extern void sdioh_sdmmc_devintr_off(sdioh_info_t *sd);
+-extern void sdioh_sdmmc_devintr_on(sdioh_info_t *sd);
+-
+-int sdio_function_init(void);
+-void sdio_function_cleanup(void);
+-
+-/* module param defaults */
+-static int clockoverride;
+-
+-module_param(clockoverride, int, 0644);
+-MODULE_PARM_DESC(clockoverride, "SDIO card clock override");
+-
+-PBCMSDH_SDMMC_INSTANCE gInstance;
+-
+-/* Maximum number of bcmsdh_sdmmc devices supported by driver */
+-#define BCMSDH_SDMMC_MAX_DEVICES 1
+-
+-extern int bcmsdh_probe(struct device *dev);
+-extern int bcmsdh_remove(struct device *dev);
+-struct device sdmmc_dev;
+-
+-static int bcmsdh_sdmmc_probe(struct sdio_func *func,
+- const struct sdio_device_id *id)
+-{
+- int ret = 0;
+- static struct sdio_func sdio_func_0;
+- sd_trace(("bcmsdh_sdmmc: %s Enter\n", __func__));
+- sd_trace(("sdio_bcmsdh: func->class=%x\n", func->class));
+- sd_trace(("sdio_vendor: 0x%04x\n", func->vendor));
+- sd_trace(("sdio_device: 0x%04x\n", func->device));
+- sd_trace(("Function#: 0x%04x\n", func->num));
+-
+- if (func->num == 1) {
+- sdio_func_0.num = 0;
+- sdio_func_0.card = func->card;
+- gInstance->func[0] = &sdio_func_0;
+- if (func->device == 0x4) { /* 4318 */
+- gInstance->func[2] = NULL;
+- sd_trace(("NIC found, calling bcmsdh_probe...\n"));
+- ret = bcmsdh_probe(&sdmmc_dev);
+- }
+- }
+-
+- gInstance->func[func->num] = func;
+-
+- if (func->num == 2) {
+- wl_cfg80211_sdio_func(func);
+- sd_trace(("F2 found, calling bcmsdh_probe...\n"));
+- ret = bcmsdh_probe(&sdmmc_dev);
+- }
+-
+- return ret;
+-}
+-
+-static void bcmsdh_sdmmc_remove(struct sdio_func *func)
+-{
+- sd_trace(("bcmsdh_sdmmc: %s Enter\n", __func__));
+- sd_info(("sdio_bcmsdh: func->class=%x\n", func->class));
+- sd_info(("sdio_vendor: 0x%04x\n", func->vendor));
+- sd_info(("sdio_device: 0x%04x\n", func->device));
+- sd_info(("Function#: 0x%04x\n", func->num));
+-
+- if (func->num == 2) {
+- sd_trace(("F2 found, calling bcmsdh_remove...\n"));
+- bcmsdh_remove(&sdmmc_dev);
+- }
+-}
+-
+-/* devices we support, null terminated */
+-static const struct sdio_device_id bcmsdh_sdmmc_ids[] = {
+- {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_DEFAULT)},
+- {SDIO_DEVICE
+- (SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4325_SDGWB)},
+- {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4325)},
+- {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)},
+- {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4319)},
+- { /* end: all zeroes */ },
+-};
+-
+-MODULE_DEVICE_TABLE(sdio, bcmsdh_sdmmc_ids);
+-
+-static struct sdio_driver bcmsdh_sdmmc_driver = {
+- .probe = bcmsdh_sdmmc_probe,
+- .remove = bcmsdh_sdmmc_remove,
+- .name = "brcmfmac",
+- .id_table = bcmsdh_sdmmc_ids,
+-};
+-
+-struct sdos_info {
+- sdioh_info_t *sd;
+- spinlock_t lock;
+-};
+-
+-int sdioh_sdmmc_osinit(sdioh_info_t *sd)
+-{
+- struct sdos_info *sdos;
+-
+- sdos = kmalloc(sizeof(struct sdos_info), GFP_ATOMIC);
+- sd->sdos_info = (void *)sdos;
+- if (sdos == NULL)
+- return -ENOMEM;
+-
+- sdos->sd = sd;
+- spin_lock_init(&sdos->lock);
+- return 0;
+-}
+-
+-void sdioh_sdmmc_osfree(sdioh_info_t *sd)
+-{
+- struct sdos_info *sdos;
+- ASSERT(sd && sd->sdos_info);
+-
+- sdos = (struct sdos_info *)sd->sdos_info;
+- kfree(sdos);
+-}
+-
+-/* Interrupt enable/disable */
+-SDIOH_API_RC sdioh_interrupt_set(sdioh_info_t *sd, bool enable)
+-{
+- unsigned long flags;
+- struct sdos_info *sdos;
+-
+- sd_trace(("%s: %s\n", __func__, enable ? "Enabling" : "Disabling"));
+-
+- sdos = (struct sdos_info *)sd->sdos_info;
+- ASSERT(sdos);
+-
+-#if !defined(OOB_INTR_ONLY)
+- if (enable && !(sd->intr_handler && sd->intr_handler_arg)) {
+- sd_err(("%s: no handler registered, will not enable\n",
+- __func__));
+- return SDIOH_API_RC_FAIL;
+- }
+-#endif /* !defined(OOB_INTR_ONLY) */
+-
+- /* Ensure atomicity for enable/disable calls */
+- spin_lock_irqsave(&sdos->lock, flags);
+-
+- sd->client_intr_enabled = enable;
+- if (enable)
+- sdioh_sdmmc_devintr_on(sd);
+- else
+- sdioh_sdmmc_devintr_off(sd);
+-
+- spin_unlock_irqrestore(&sdos->lock, flags);
+-
+- return SDIOH_API_RC_SUCCESS;
+-}
+-
+-/*
+- * module init
+-*/
+-int sdio_function_init(void)
+-{
+- int error = 0;
+- sd_trace(("bcmsdh_sdmmc: %s Enter\n", __func__));
+-
+- gInstance = kzalloc(sizeof(BCMSDH_SDMMC_INSTANCE), GFP_KERNEL);
+- if (!gInstance)
+- return -ENOMEM;
+-
+- memset(&sdmmc_dev, 0, sizeof(sdmmc_dev));
+- error = sdio_register_driver(&bcmsdh_sdmmc_driver);
+-
+- return error;
+-}
+-
+-/*
+- * module cleanup
+-*/
+-extern int bcmsdh_remove(struct device *dev);
+-void sdio_function_cleanup(void)
+-{
+- sd_trace(("%s Enter\n", __func__));
+-
+- sdio_unregister_driver(&bcmsdh_sdmmc_driver);
+-
+- kfree(gInstance);
+-}
+diff --git a/drivers/staging/brcm80211/brcmfmac/dhd.h b/drivers/staging/brcm80211/brcmfmac/dhd.h
+deleted file mode 100644
+index a726b49..0000000
+--- a/drivers/staging/brcm80211/brcmfmac/dhd.h
++++ /dev/null
+@@ -1,414 +0,0 @@
+-/*
+- * Copyright (c) 2010 Broadcom Corporation
+- *
+- * 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.
+- */
+-
+-/****************
+- * Common types *
+- */
+-
+-#ifndef _dhd_h_
+-#define _dhd_h_
+-
+-#include <linux/sched.h>
+-#include <linux/init.h>
+-#include <linux/kernel.h>
+-#include <linux/slab.h>
+-#include <linux/skbuff.h>
+-#include <linux/netdevice.h>
+-#include <linux/etherdevice.h>
+-#include <linux/random.h>
+-#include <linux/spinlock.h>
+-#include <linux/ethtool.h>
+-#include <linux/suspend.h>
+-#include <asm/uaccess.h>
+-#include <asm/unaligned.h>
+-/* The kernel threading is sdio-specific */
+-
+-#include <wlioctl.h>
+-
+-/* Forward decls */
+-struct dhd_bus;
+-struct dhd_prot;
+-struct dhd_info;
+-
+-/* The level of bus communication with the dongle */
+-enum dhd_bus_state {
+- DHD_BUS_DOWN, /* Not ready for frame transfers */
+- DHD_BUS_LOAD, /* Download access only (CPU reset) */
+- DHD_BUS_DATA /* Ready for frame transfers */
+-};
+-
+-/* Common structure for module and instance linkage */
+-typedef struct dhd_pub {
+- /* Linkage ponters */
+- struct dhd_bus *bus; /* Bus module handle */
+- struct dhd_prot *prot; /* Protocol module handle */
+- struct dhd_info *info; /* Info module handle */
+-
+- /* Internal dhd items */
+- bool up; /* Driver up/down (to OS) */
+- bool txoff; /* Transmit flow-controlled */
+- bool dongle_reset; /* true = DEVRESET put dongle into reset */
+- enum dhd_bus_state busstate;
+- uint hdrlen; /* Total DHD header length (proto + bus) */
+- uint maxctl; /* Max size rxctl request from proto to bus */
+- uint rxsz; /* Rx buffer size bus module should use */
+- u8 wme_dp; /* wme discard priority */
+-
+- /* Dongle media info */
+- bool iswl; /* Dongle-resident driver is wl */
+- unsigned long drv_version; /* Version of dongle-resident driver */
+- u8 mac[ETH_ALEN]; /* MAC address obtained from dongle */
+- dngl_stats_t dstats; /* Stats for dongle-based data */
+-
+- /* Additional stats for the bus level */
+- unsigned long tx_packets; /* Data packets sent to dongle */
+- unsigned long tx_multicast; /* Multicast data packets sent to dongle */
+- unsigned long tx_errors; /* Errors in sending data to dongle */
+- unsigned long tx_ctlpkts; /* Control packets sent to dongle */
+- unsigned long tx_ctlerrs; /* Errors sending control frames to dongle */
+- unsigned long rx_packets; /* Packets sent up the network interface */
+- unsigned long rx_multicast; /* Multicast packets sent up the network
+- interface */
+- unsigned long rx_errors; /* Errors processing rx data packets */
+- unsigned long rx_ctlpkts; /* Control frames processed from dongle */
+- unsigned long rx_ctlerrs; /* Errors in processing rx control frames */
+- unsigned long rx_dropped; /* Packets dropped locally (no memory) */
+- unsigned long rx_flushed; /* Packets flushed due to
+- unscheduled sendup thread */
+- unsigned long wd_dpc_sched; /* Number of times dhd dpc scheduled by
+- watchdog timer */
+-
+- unsigned long rx_readahead_cnt; /* Number of packets where header read-ahead
+- was used. */
+- unsigned long tx_realloc; /* Number of tx packets we had to realloc for
+- headroom */
+- unsigned long fc_packets; /* Number of flow control pkts recvd */
+-
+- /* Last error return */
+- int bcmerror;
+- uint tickcnt;
+-
+- /* Last error from dongle */
+- int dongle_error;
+-
+- /* Suspend disable flag flag */
+- int suspend_disable_flag; /* "1" to disable all extra powersaving
+- during suspend */
+- int in_suspend; /* flag set to 1 when early suspend called */
+-#ifdef PNO_SUPPORT
+- int pno_enable; /* pno status : "1" is pno enable */
+-#endif /* PNO_SUPPORT */
+- int dtim_skip; /* dtim skip , default 0 means wake each dtim */
+-
+- /* Pkt filter defination */
+- char *pktfilter[100];
+- int pktfilter_count;
+-
+- u8 country_code[WLC_CNTRY_BUF_SZ];
+- char eventmask[WL_EVENTING_MASK_LEN];
+-
+-} dhd_pub_t;
+-
+-#if defined(CONFIG_PM_SLEEP)
+-extern atomic_t dhd_mmc_suspend;
+-#define DHD_PM_RESUME_WAIT_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a);
+-#define _DHD_PM_RESUME_WAIT(a, b) do { \
+- int retry = 0; \
+- while (atomic_read(&dhd_mmc_suspend) && retry++ != b) { \
+- wait_event_timeout(a, false, HZ/100); \
+- } \
+- } while (0)
+-#define DHD_PM_RESUME_WAIT(a) _DHD_PM_RESUME_WAIT(a, 30)
+-#define DHD_PM_RESUME_WAIT_FOREVER(a) _DHD_PM_RESUME_WAIT(a, ~0)
+-#define DHD_PM_RESUME_RETURN_ERROR(a) \
+- do { if (atomic_read(&dhd_mmc_suspend)) return a; } while (0)
+-#define DHD_PM_RESUME_RETURN do { \
+- if (atomic_read(&dhd_mmc_suspend)) \
+- return; \
+- } while (0)
+-
+-#define DHD_SPINWAIT_SLEEP_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a);
+-#define SPINWAIT_SLEEP(a, exp, us) do { \
+- uint countdown = (us) + 9999; \
+- while ((exp) && (countdown >= 10000)) { \
+- wait_event_timeout(a, false, HZ/100); \
+- countdown -= 10000; \
+- } \
+- } while (0)
+-
+-#else
+-
+-#define DHD_PM_RESUME_WAIT_INIT(a)
+-#define DHD_PM_RESUME_WAIT(a)
+-#define DHD_PM_RESUME_WAIT_FOREVER(a)
+-#define DHD_PM_RESUME_RETURN_ERROR(a)
+-#define DHD_PM_RESUME_RETURN
+-
+-#define DHD_SPINWAIT_SLEEP_INIT(a)
+-#define SPINWAIT_SLEEP(a, exp, us) do { \
+- uint countdown = (us) + 9; \
+- while ((exp) && (countdown >= 10)) { \
+- udelay(10); \
+- countdown -= 10; \
+- } \
+- } while (0)
+-
+-#endif /* defined(CONFIG_PM_SLEEP) */
+-#define DHD_IF_VIF 0x01 /* Virtual IF (Hidden from user) */
+-
+-static inline void MUTEX_LOCK_INIT(dhd_pub_t *dhdp)
+-{
+-}
+-
+-static inline void MUTEX_LOCK(dhd_pub_t *dhdp)
+-{
+-}
+-
+-static inline void MUTEX_UNLOCK(dhd_pub_t *dhdp)
+-{
+-}
+-
+-static inline void MUTEX_LOCK_SOFTAP_SET_INIT(dhd_pub_t *dhdp)
+-{
+-}
+-
+-static inline void MUTEX_LOCK_SOFTAP_SET(dhd_pub_t *dhdp)
+-{
+-}
+-
+-static inline void MUTEX_UNLOCK_SOFTAP_SET(dhd_pub_t *dhdp)
+-{
+-}
+-
+-static inline void MUTEX_LOCK_WL_SCAN_SET_INIT(void)
+-{
+-}
+-
+-static inline void MUTEX_LOCK_WL_SCAN_SET(void)
+-{
+-}
+-
+-static inline void MUTEX_UNLOCK_WL_SCAN_SET(void)
+-{
+-}
+-
+-typedef struct dhd_if_event {
+- u8 ifidx;
+- u8 action;
+- u8 flags;
+- u8 bssidx;
+-} dhd_if_event_t;
+-
+-/*
+- * Exported from dhd OS modules (dhd_linux/dhd_ndis)
+- */
+-
+-/* Indication from bus module regarding presence/insertion of dongle.
+- * Return dhd_pub_t pointer, used as handle to OS module in later calls.
+- * Returned structure should have bus and prot pointers filled in.
+- * bus_hdrlen specifies required headroom for bus module header.
+- */
+-extern dhd_pub_t *dhd_attach(struct dhd_bus *bus,
+- uint bus_hdrlen);
+-extern int dhd_net_attach(dhd_pub_t *dhdp, int idx);
+-
+-/* Indication from bus module regarding removal/absence of dongle */
+-extern void dhd_detach(dhd_pub_t *dhdp);
+-
+-/* Indication from bus module to change flow-control state */
+-extern void dhd_txflowcontrol(dhd_pub_t *dhdp, int ifidx, bool on);
+-
+-extern bool dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q,
+- struct sk_buff *pkt, int prec);
+-
+-/* Receive frame for delivery to OS. Callee disposes of rxp. */
+-extern void dhd_rx_frame(dhd_pub_t *dhdp, int ifidx,
+- struct sk_buff *rxp, int numpkt);
+-
+-/* Return pointer to interface name */
+-extern char *dhd_ifname(dhd_pub_t *dhdp, int idx);
+-
+-/* Request scheduling of the bus dpc */
+-extern void dhd_sched_dpc(dhd_pub_t *dhdp);
+-
+-/* Notify tx completion */
+-extern void dhd_txcomplete(dhd_pub_t *dhdp, struct sk_buff *txp, bool success);
+-
+-/* Query ioctl */
+-extern int dhdcdc_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf,
+- uint len);
+-
+-/* OS independent layer functions */
+-extern int dhd_os_proto_block(dhd_pub_t *pub);
+-extern int dhd_os_proto_unblock(dhd_pub_t *pub);
+-extern int dhd_os_ioctl_resp_wait(dhd_pub_t *pub, uint *condition,
+- bool *pending);
+-extern int dhd_os_ioctl_resp_wake(dhd_pub_t *pub);
+-extern unsigned int dhd_os_get_ioctl_resp_timeout(void);
+-extern void dhd_os_set_ioctl_resp_timeout(unsigned int timeout_msec);
+-extern void *dhd_os_open_image(char *filename);
+-extern int dhd_os_get_image_block(char *buf, int len, void *image);
+-extern void dhd_os_close_image(void *image);
+-extern void dhd_os_wd_timer(void *bus, uint wdtick);
+-extern void dhd_os_sdlock(dhd_pub_t *pub);
+-extern void dhd_os_sdunlock(dhd_pub_t *pub);
+-extern void dhd_os_sdlock_txq(dhd_pub_t *pub);
+-extern void dhd_os_sdunlock_txq(dhd_pub_t *pub);
+-extern void dhd_os_sdlock_rxq(dhd_pub_t *pub);
+-extern void dhd_os_sdunlock_rxq(dhd_pub_t *pub);
+-extern void dhd_os_sdlock_sndup_rxq(dhd_pub_t *pub);
+-extern void dhd_customer_gpio_wlan_ctrl(int onoff);
+-extern int dhd_custom_get_mac_address(unsigned char *buf);
+-extern void dhd_os_sdunlock_sndup_rxq(dhd_pub_t *pub);
+-extern void dhd_os_sdlock_eventq(dhd_pub_t *pub);
+-extern void dhd_os_sdunlock_eventq(dhd_pub_t *pub);
+-#ifdef DHD_DEBUG
+-extern int write_to_file(dhd_pub_t *dhd, u8 *buf, int size);
+-#endif /* DHD_DEBUG */
+-#if defined(OOB_INTR_ONLY)
+-extern int dhd_customer_oob_irq_map(unsigned long *irq_flags_ptr);
+-#endif /* defined(OOB_INTR_ONLY) */
+-extern void dhd_os_sdtxlock(dhd_pub_t *pub);
+-extern void dhd_os_sdtxunlock(dhd_pub_t *pub);
+-
+-int setScheduler(struct task_struct *p, int policy, struct sched_param *param);
+-
+-typedef struct {
+- u32 limit; /* Expiration time (usec) */
+- u32 increment; /* Current expiration increment (usec) */
+- u32 elapsed; /* Current elapsed time (usec) */
+- u32 tick; /* O/S tick time (usec) */
+-} dhd_timeout_t;
+-
+-extern void dhd_timeout_start(dhd_timeout_t *tmo, uint usec);
+-extern int dhd_timeout_expired(dhd_timeout_t *tmo);
+-
+-extern int dhd_ifname2idx(struct dhd_info *dhd, char *name);
+-extern u8 *dhd_bssidx2bssid(dhd_pub_t *dhd, int idx);
+-extern int wl_host_event(struct dhd_info *dhd, int *idx, void *pktdata,
+- wl_event_msg_t *, void **data_ptr);
+-
+-extern void dhd_common_init(void);
+-
+-extern int dhd_add_if(struct dhd_info *dhd, int ifidx, void *handle,
+- char *name, u8 *mac_addr, u32 flags, u8 bssidx);
+-extern void dhd_del_if(struct dhd_info *dhd, int ifidx);
+-
+-extern void dhd_vif_add(struct dhd_info *dhd, int ifidx, char *name);
+-extern void dhd_vif_del(struct dhd_info *dhd, int ifidx);
+-
+-extern void dhd_event(struct dhd_info *dhd, char *evpkt, int evlen, int ifidx);
+-extern void dhd_vif_sendup(struct dhd_info *dhd, int ifidx, unsigned char * cp,
+- int len);
+-
+-/* Send packet to dongle via data channel */
+-extern int dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, struct sk_buff *pkt);
+-
+-/* Send event to host */
+-extern void dhd_sendup_event(dhd_pub_t *dhdp, wl_event_msg_t *event,
+- void *data);
+-extern int dhd_bus_devreset(dhd_pub_t *dhdp, u8 flag);
+-extern uint dhd_bus_status(dhd_pub_t *dhdp);
+-extern int dhd_bus_start(dhd_pub_t *dhdp);
+-
+-enum cust_gpio_modes {
+- WLAN_RESET_ON,
+- WLAN_RESET_OFF,
+- WLAN_POWER_ON,
+- WLAN_POWER_OFF
+-};
+-/*
+- * Insmod parameters for debug/test
+- */
+-
+-/* Watchdog timer interval */
+-extern uint dhd_watchdog_ms;
+-
+-#if defined(DHD_DEBUG)
+-/* Console output poll interval */
+-extern uint dhd_console_ms;
+-#endif /* defined(DHD_DEBUG) */
+-
+-/* Use interrupts */
+-extern uint dhd_intr;
+-
+-/* Use polling */
+-extern uint dhd_poll;
+-
+-/* ARP offload agent mode */
+-extern uint dhd_arp_mode;
+-
+-/* ARP offload enable */
+-extern uint dhd_arp_enable;
+-
+-/* Pkt filte enable control */
+-extern uint dhd_pkt_filter_enable;
+-
+-/* Pkt filter init setup */
+-extern uint dhd_pkt_filter_init;
+-
+-/* Pkt filter mode control */
+-extern uint dhd_master_mode;
+-
+-/* Roaming mode control */
+-extern uint dhd_roam;
+-
+-/* Roaming mode control */
+-extern uint dhd_radio_up;
+-
+-/* Initial idletime ticks (may be -1 for immediate idle, 0 for no idle) */
+-extern int dhd_idletime;
+-#define DHD_IDLETIME_TICKS 1
+-
+-/* SDIO Drive Strength */
+-extern uint dhd_sdiod_drive_strength;
+-
+-/* Override to force tx queueing all the time */
+-extern uint dhd_force_tx_queueing;
+-
+-#ifdef SDTEST
+-/* Echo packet generator (SDIO), pkts/s */
+-extern uint dhd_pktgen;
+-
+-/* Echo packet len (0 => sawtooth, max 1800) */
+-extern uint dhd_pktgen_len;
+-#define MAX_PKTGEN_LEN 1800
+-#endif
+-
+-/* optionally set by a module_param_string() */
+-#define MOD_PARAM_PATHLEN 2048
+-extern char fw_path[MOD_PARAM_PATHLEN];
+-extern char nv_path[MOD_PARAM_PATHLEN];
+-
+-/* For supporting multiple interfaces */
+-#define DHD_MAX_IFS 16
+-#define DHD_DEL_IF -0xe
+-#define DHD_BAD_IF -0xf
+-
+-extern void dhd_wait_for_event(dhd_pub_t *dhd, bool * lockvar);
+-extern void dhd_wait_event_wakeup(dhd_pub_t *dhd);
+-
+-extern u32 g_assert_type;
+-
+-#ifdef BCMDBG
+-#define ASSERT(exp) \
+- do { if (!(exp)) osl_assert(#exp, __FILE__, __LINE__); } while (0)
+-extern void osl_assert(char *exp, char *file, int line);
+-#else
+-#define ASSERT(exp) do {} while (0)
+-#endif /* defined(BCMDBG) */
+-
+-#endif /* _dhd_h_ */
+diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_bus.h b/drivers/staging/brcm80211/brcmfmac/dhd_bus.h
+deleted file mode 100644
+index 065f1ae..0000000
+--- a/drivers/staging/brcm80211/brcmfmac/dhd_bus.h
++++ /dev/null
+@@ -1,82 +0,0 @@
+-/*
+- * Copyright (c) 2010 Broadcom Corporation
+- *
+- * 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 _dhd_bus_h_
+-#define _dhd_bus_h_
+-
+-/*
+- * Exported from dhd bus module (dhd_usb, dhd_sdio)
+- */
+-
+-/* Indicate (dis)interest in finding dongles. */
+-extern int dhd_bus_register(void);
+-extern void dhd_bus_unregister(void);
+-
+-/* Download firmware image and nvram image */
+-extern bool dhd_bus_download_firmware(struct dhd_bus *bus,
+- char *fw_path, char *nv_path);
+-
+-/* Stop bus module: clear pending frames, disable data flow */
+-extern void dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex);
+-
+-/* Initialize bus module: prepare for communication w/dongle */
+-extern int dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex);
+-
+-/* Send a data frame to the dongle. Callee disposes of txp. */
+-extern int dhd_bus_txdata(struct dhd_bus *bus, struct sk_buff *txp);
+-
+-/* Send/receive a control message to/from the dongle.
+- * Expects caller to enforce a single outstanding transaction.
+- */
+-extern int dhd_bus_txctl(struct dhd_bus *bus, unsigned char *msg, uint msglen);
+-extern int dhd_bus_rxctl(struct dhd_bus *bus, unsigned char *msg, uint msglen);
+-
+-/* Watchdog timer function */
+-extern bool dhd_bus_watchdog(dhd_pub_t *dhd);
+-
+-#ifdef DHD_DEBUG
+-/* Device console input function */
+-extern int dhd_bus_console_in(dhd_pub_t *dhd, unsigned char *msg, uint msglen);
+-#endif /* DHD_DEBUG */
+-
+-/* Deferred processing for the bus, return true requests reschedule */
+-extern bool dhd_bus_dpc(struct dhd_bus *bus);
+-extern void dhd_bus_isr(bool *InterruptRecognized,
+- bool *QueueMiniportHandleInterrupt, void *arg);
+-
+-/* Check for and handle local prot-specific iovar commands */
+-extern int dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name,
+- void *params, int plen, void *arg, int len,
+- bool set);
+-
+-/* Add bus dump output to a buffer */
+-extern void dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf);
+-
+-/* Clear any bus counters */
+-extern void dhd_bus_clearcounts(dhd_pub_t *dhdp);
+-
+-/* return the dongle chipid */
+-extern uint dhd_bus_chip(struct dhd_bus *bus);
+-
+-/* Set user-specified nvram parameters. */
+-extern void dhd_bus_set_nvram_params(struct dhd_bus *bus,
+- const char *nvram_params);
+-
+-extern void *dhd_bus_pub(struct dhd_bus *bus);
+-extern void *dhd_bus_txq(struct dhd_bus *bus);
+-extern uint dhd_bus_hdrlen(struct dhd_bus *bus);
+-
+-#endif /* _dhd_bus_h_ */
+diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c b/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c
+deleted file mode 100644
+index ba5a5cb..0000000
+--- a/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c
++++ /dev/null
+@@ -1,474 +0,0 @@
+-/*
+- * Copyright (c) 2010 Broadcom Corporation
+- *
+- * 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/types.h>
+-#include <linux/netdevice.h>
+-#include <bcmdefs.h>
+-
+-#include <bcmutils.h>
+-#include <bcmcdc.h>
+-
+-#include <dngl_stats.h>
+-#include <dhd.h>
+-#include <dhd_proto.h>
+-#include <dhd_bus.h>
+-#include <dhd_dbg.h>
+-#ifdef CUSTOMER_HW2
+-int wifi_get_mac_addr(unsigned char *buf);
+-#endif
+-
+-extern int dhd_preinit_ioctls(dhd_pub_t *dhd);
+-
+-/* Packet alignment for most efficient SDIO (can change based on platform) */
+-#ifndef DHD_SDALIGN
+-#define DHD_SDALIGN 32
+-#endif
+-#if !ISPOWEROF2(DHD_SDALIGN)
+-#error DHD_SDALIGN is not a power of 2!
+-#endif
+-
+-#define RETRIES 2 /* # of retries to retrieve matching ioctl response */
+-#define BUS_HEADER_LEN (16+DHD_SDALIGN) /* Must be atleast SDPCM_RESERVE
+- * defined in dhd_sdio.c
+- * (amount of header tha might be added)
+- * plus any space that might be needed
+- * for alignment padding.
+- */
+-#define ROUND_UP_MARGIN 2048 /* Biggest SDIO block size possible for
+- * round off at the end of buffer
+- */
+-
+-typedef struct dhd_prot {
+- u16 reqid;
+- u8 pending;
+- u32 lastcmd;
+- u8 bus_header[BUS_HEADER_LEN];
+- cdc_ioctl_t msg;
+- unsigned char buf[WLC_IOCTL_MAXLEN + ROUND_UP_MARGIN];
+-} dhd_prot_t;
+-
+-static int dhdcdc_msg(dhd_pub_t *dhd)
+-{
+- dhd_prot_t *prot = dhd->prot;
+- int len = le32_to_cpu(prot->msg.len) + sizeof(cdc_ioctl_t);
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- /* NOTE : cdc->msg.len holds the desired length of the buffer to be
+- * returned. Only up to CDC_MAX_MSG_SIZE of this buffer area
+- * is actually sent to the dongle
+- */
+- if (len > CDC_MAX_MSG_SIZE)
+- len = CDC_MAX_MSG_SIZE;
+-
+- /* Send request */
+- return dhd_bus_txctl(dhd->bus, (unsigned char *)&prot->msg, len);
+-}
+-
+-static int dhdcdc_cmplt(dhd_pub_t *dhd, u32 id, u32 len)
+-{
+- int ret;
+- dhd_prot_t *prot = dhd->prot;
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- do {
+- ret =
+- dhd_bus_rxctl(dhd->bus, (unsigned char *)&prot->msg,
+- len + sizeof(cdc_ioctl_t));
+- if (ret < 0)
+- break;
+- } while (CDC_IOC_ID(le32_to_cpu(prot->msg.flags)) != id);
+-
+- return ret;
+-}
+-
+-int
+-dhdcdc_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len)
+-{
+- dhd_prot_t *prot = dhd->prot;
+- cdc_ioctl_t *msg = &prot->msg;
+- void *info;
+- int ret = 0, retries = 0;
+- u32 id, flags = 0;
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+- DHD_CTL(("%s: cmd %d len %d\n", __func__, cmd, len));
+-
+- /* Respond "bcmerror" and "bcmerrorstr" with local cache */
+- if (cmd == WLC_GET_VAR && buf) {
+- if (!strcmp((char *)buf, "bcmerrorstr")) {
+- strncpy((char *)buf, "bcm_error",
+- BCME_STRLEN);
+- goto done;
+- } else if (!strcmp((char *)buf, "bcmerror")) {
+- *(int *)buf = dhd->dongle_error;
+- goto done;
+- }
+- }
+-
+- memset(msg, 0, sizeof(cdc_ioctl_t));
+-
+- msg->cmd = cpu_to_le32(cmd);
+- msg->len = cpu_to_le32(len);
+- msg->flags = (++prot->reqid << CDCF_IOC_ID_SHIFT);
+- CDC_SET_IF_IDX(msg, ifidx);
+- msg->flags = cpu_to_le32(msg->flags);
+-
+- if (buf)
+- memcpy(prot->buf, buf, len);
+-
+- ret = dhdcdc_msg(dhd);
+- if (ret < 0) {
+- DHD_ERROR(("dhdcdc_query_ioctl: dhdcdc_msg failed w/status "
+- "%d\n", ret));
+- goto done;
+- }
+-
+-retry:
+- /* wait for interrupt and get first fragment */
+- ret = dhdcdc_cmplt(dhd, prot->reqid, len);
+- if (ret < 0)
+- goto done;
+-
+- flags = le32_to_cpu(msg->flags);
+- id = (flags & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT;
+-
+- if ((id < prot->reqid) && (++retries < RETRIES))
+- goto retry;
+- if (id != prot->reqid) {
+- DHD_ERROR(("%s: %s: unexpected request id %d (expected %d)\n",
+- dhd_ifname(dhd, ifidx), __func__, id, prot->reqid));
+- ret = -EINVAL;
+- goto done;
+- }
+-
+- /* Check info buffer */
+- info = (void *)&msg[1];
+-
+- /* Copy info buffer */
+- if (buf) {
+- if (ret < (int)len)
+- len = ret;
+- memcpy(buf, info, len);
+- }
+-
+- /* Check the ERROR flag */
+- if (flags & CDCF_IOC_ERROR) {
+- ret = le32_to_cpu(msg->status);
+- /* Cache error from dongle */
+- dhd->dongle_error = ret;
+- }
+-
+-done:
+- return ret;
+-}
+-
+-int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len)
+-{
+- dhd_prot_t *prot = dhd->prot;
+- cdc_ioctl_t *msg = &prot->msg;
+- int ret = 0;
+- u32 flags, id;
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+- DHD_CTL(("%s: cmd %d len %d\n", __func__, cmd, len));
+-
+- memset(msg, 0, sizeof(cdc_ioctl_t));
+-
+- msg->cmd = cpu_to_le32(cmd);
+- msg->len = cpu_to_le32(len);
+- msg->flags = (++prot->reqid << CDCF_IOC_ID_SHIFT) | CDCF_IOC_SET;
+- CDC_SET_IF_IDX(msg, ifidx);
+- msg->flags = cpu_to_le32(msg->flags);
+-
+- if (buf)
+- memcpy(prot->buf, buf, len);
+-
+- ret = dhdcdc_msg(dhd);
+- if (ret < 0)
+- goto done;
+-
+- ret = dhdcdc_cmplt(dhd, prot->reqid, len);
+- if (ret < 0)
+- goto done;
+-
+- flags = le32_to_cpu(msg->flags);
+- id = (flags & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT;
+-
+- if (id != prot->reqid) {
+- DHD_ERROR(("%s: %s: unexpected request id %d (expected %d)\n",
+- dhd_ifname(dhd, ifidx), __func__, id, prot->reqid));
+- ret = -EINVAL;
+- goto done;
+- }
+-
+- /* Check the ERROR flag */
+- if (flags & CDCF_IOC_ERROR) {
+- ret = le32_to_cpu(msg->status);
+- /* Cache error from dongle */
+- dhd->dongle_error = ret;
+- }
+-
+-done:
+- return ret;
+-}
+-
+-extern int dhd_bus_interface(struct dhd_bus *bus, uint arg, void *arg2);
+-int
+-dhd_prot_ioctl(dhd_pub_t *dhd, int ifidx, wl_ioctl_t *ioc, void *buf, int len)
+-{
+- dhd_prot_t *prot = dhd->prot;
+- int ret = -1;
+-
+- if (dhd->busstate == DHD_BUS_DOWN) {
+- DHD_ERROR(("%s : bus is down. we have nothing to do\n",
+- __func__));
+- return ret;
+- }
+- dhd_os_proto_block(dhd);
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- ASSERT(len <= WLC_IOCTL_MAXLEN);
+-
+- if (len > WLC_IOCTL_MAXLEN)
+- goto done;
+-
+- if (prot->pending == true) {
+- DHD_TRACE(("CDC packet is pending!!!! cmd=0x%x (%lu) "
+- "lastcmd=0x%x (%lu)\n",
+- ioc->cmd, (unsigned long)ioc->cmd, prot->lastcmd,
+- (unsigned long)prot->lastcmd));
+- if ((ioc->cmd == WLC_SET_VAR) || (ioc->cmd == WLC_GET_VAR))
+- DHD_TRACE(("iovar cmd=%s\n", (char *)buf));
+-
+- goto done;
+- }
+-
+- prot->pending = true;
+- prot->lastcmd = ioc->cmd;
+- if (ioc->set)
+- ret = dhdcdc_set_ioctl(dhd, ifidx, ioc->cmd, buf, len);
+- else {
+- ret = dhdcdc_query_ioctl(dhd, ifidx, ioc->cmd, buf, len);
+- if (ret > 0)
+- ioc->used = ret - sizeof(cdc_ioctl_t);
+- }
+-
+- /* Too many programs assume ioctl() returns 0 on success */
+- if (ret >= 0)
+- ret = 0;
+- else {
+- cdc_ioctl_t *msg = &prot->msg;
+- /* len == needed when set/query fails from dongle */
+- ioc->needed = le32_to_cpu(msg->len);
+- }
+-
+- /* Intercept the wme_dp ioctl here */
+- if ((!ret) && (ioc->cmd == WLC_SET_VAR) && (!strcmp(buf, "wme_dp"))) {
+- int slen, val = 0;
+-
+- slen = strlen("wme_dp") + 1;
+- if (len >= (int)(slen + sizeof(int)))
+- memcpy(&val, (char *)buf + slen, sizeof(int));
+- dhd->wme_dp = (u8) le32_to_cpu(val);
+- }
+-
+- prot->pending = false;
+-
+-done:
+- dhd_os_proto_unblock(dhd);
+-
+- return ret;
+-}
+-
+-#define PKTSUMNEEDED(skb) \
+- (((struct sk_buff *)(skb))->ip_summed == CHECKSUM_PARTIAL)
+-#define PKTSETSUMGOOD(skb, x) \
+- (((struct sk_buff *)(skb))->ip_summed = \
+- ((x) ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE))
+-
+-/* PKTSETSUMNEEDED and PKTSUMGOOD are not possible because
+- skb->ip_summed is overloaded */
+-
+-int
+-dhd_prot_iovar_op(dhd_pub_t *dhdp, const char *name,
+- void *params, int plen, void *arg, int len, bool set)
+-{
+- return -ENOTSUPP;
+-}
+-
+-void dhd_prot_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf)
+-{
+- bcm_bprintf(strbuf, "Protocol CDC: reqid %d\n", dhdp->prot->reqid);
+-}
+-
+-void dhd_prot_hdrpush(dhd_pub_t *dhd, int ifidx, struct sk_buff *pktbuf)
+-{
+-#ifdef BDC
+- struct bdc_header *h;
+-#endif /* BDC */
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+-#ifdef BDC
+- /* Push BDC header used to convey priority for buses that don't */
+-
+- skb_push(pktbuf, BDC_HEADER_LEN);
+-
+- h = (struct bdc_header *)(pktbuf->data);
+-
+- h->flags = (BDC_PROTO_VER << BDC_FLAG_VER_SHIFT);
+- if (PKTSUMNEEDED(pktbuf))
+- h->flags |= BDC_FLAG_SUM_NEEDED;
+-
+- h->priority = (pktbuf->priority & BDC_PRIORITY_MASK);
+- h->flags2 = 0;
+- h->rssi = 0;
+-#endif /* BDC */
+- BDC_SET_IF_IDX(h, ifidx);
+-}
+-
+-int dhd_prot_hdrpull(dhd_pub_t *dhd, int *ifidx, struct sk_buff *pktbuf)
+-{
+-#ifdef BDC
+- struct bdc_header *h;
+-#endif
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+-#ifdef BDC
+- /* Pop BDC header used to convey priority for buses that don't */
+-
+- if (pktbuf->len < BDC_HEADER_LEN) {
+- DHD_ERROR(("%s: rx data too short (%d < %d)\n", __func__,
+- pktbuf->len, BDC_HEADER_LEN));
+- return -EBADE;
+- }
+-
+- h = (struct bdc_header *)(pktbuf->data);
+-
+- *ifidx = BDC_GET_IF_IDX(h);
+- if (*ifidx >= DHD_MAX_IFS) {
+- DHD_ERROR(("%s: rx data ifnum out of range (%d)\n",
+- __func__, *ifidx));
+- return -EBADE;
+- }
+-
+- if (((h->flags & BDC_FLAG_VER_MASK) >> BDC_FLAG_VER_SHIFT) !=
+- BDC_PROTO_VER) {
+- DHD_ERROR(("%s: non-BDC packet received, flags 0x%x\n",
+- dhd_ifname(dhd, *ifidx), h->flags));
+- return -EBADE;
+- }
+-
+- if (h->flags & BDC_FLAG_SUM_GOOD) {
+- DHD_INFO(("%s: BDC packet received with good rx-csum, "
+- "flags 0x%x\n",
+- dhd_ifname(dhd, *ifidx), h->flags));
+- PKTSETSUMGOOD(pktbuf, true);
+- }
+-
+- pktbuf->priority = h->priority & BDC_PRIORITY_MASK;
+-
+- skb_pull(pktbuf, BDC_HEADER_LEN);
+-#endif /* BDC */
+-
+- return 0;
+-}
+-
+-int dhd_prot_attach(dhd_pub_t *dhd)
+-{
+- dhd_prot_t *cdc;
+-
+- cdc = kzalloc(sizeof(dhd_prot_t), GFP_ATOMIC);
+- if (!cdc) {
+- DHD_ERROR(("%s: kmalloc failed\n", __func__));
+- goto fail;
+- }
+-
+- /* ensure that the msg buf directly follows the cdc msg struct */
+- if ((unsigned long)(&cdc->msg + 1) != (unsigned long)cdc->buf) {
+- DHD_ERROR(("dhd_prot_t is not correctly defined\n"));
+- goto fail;
+- }
+-
+- dhd->prot = cdc;
+-#ifdef BDC
+- dhd->hdrlen += BDC_HEADER_LEN;
+-#endif
+- dhd->maxctl = WLC_IOCTL_MAXLEN + sizeof(cdc_ioctl_t) + ROUND_UP_MARGIN;
+- return 0;
+-
+-fail:
+- kfree(cdc);
+- return -ENOMEM;
+-}
+-
+-/* ~NOTE~ What if another thread is waiting on the semaphore? Holding it? */
+-void dhd_prot_detach(dhd_pub_t *dhd)
+-{
+- kfree(dhd->prot);
+- dhd->prot = NULL;
+-}
+-
+-void dhd_prot_dstats(dhd_pub_t *dhd)
+-{
+- /* No stats from dongle added yet, copy bus stats */
+- dhd->dstats.tx_packets = dhd->tx_packets;
+- dhd->dstats.tx_errors = dhd->tx_errors;
+- dhd->dstats.rx_packets = dhd->rx_packets;
+- dhd->dstats.rx_errors = dhd->rx_errors;
+- dhd->dstats.rx_dropped = dhd->rx_dropped;
+- dhd->dstats.multicast = dhd->rx_multicast;
+- return;
+-}
+-
+-int dhd_prot_init(dhd_pub_t *dhd)
+-{
+- int ret = 0;
+- char buf[128];
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- dhd_os_proto_block(dhd);
+-
+- /* Get the device MAC address */
+- strcpy(buf, "cur_etheraddr");
+- ret = dhdcdc_query_ioctl(dhd, 0, WLC_GET_VAR, buf, sizeof(buf));
+- if (ret < 0) {
+- dhd_os_proto_unblock(dhd);
+- return ret;
+- }
+- memcpy(dhd->mac, buf, ETH_ALEN);
+-
+- dhd_os_proto_unblock(dhd);
+-
+-#ifdef EMBEDDED_PLATFORM
+- ret = dhd_preinit_ioctls(dhd);
+-#endif /* EMBEDDED_PLATFORM */
+-
+- /* Always assumes wl for now */
+- dhd->iswl = true;
+-
+- return ret;
+-}
+-
+-void dhd_prot_stop(dhd_pub_t *dhd)
+-{
+- /* Nothing to do for CDC */
+-}
+diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_common.c b/drivers/staging/brcm80211/brcmfmac/dhd_common.c
+deleted file mode 100644
+index 0bfb93c..0000000
+--- a/drivers/staging/brcm80211/brcmfmac/dhd_common.c
++++ /dev/null
+@@ -1,1848 +0,0 @@
+-/*
+- * Copyright (c) 2010 Broadcom Corporation
+- *
+- * 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/kernel.h>
+-#include <linux/string.h>
+-#include <bcmdefs.h>
+-#include <linux/netdevice.h>
+-#include <bcmutils.h>
+-#include <dngl_stats.h>
+-#include <dhd.h>
+-#include <dhd_bus.h>
+-#include <dhd_proto.h>
+-#include <dhd_dbg.h>
+-#include <msgtrace.h>
+-#include <wlioctl.h>
+-
+-int dhd_msg_level;
+-char fw_path[MOD_PARAM_PATHLEN];
+-char nv_path[MOD_PARAM_PATHLEN];
+-
+-/* Last connection success/failure status */
+-u32 dhd_conn_event;
+-u32 dhd_conn_status;
+-u32 dhd_conn_reason;
+-
+-extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf,
+- uint len);
+-extern void dhd_ind_scan_confirm(void *h, bool status);
+-extern int dhd_wl_ioctl(dhd_pub_t *dhd, uint cmd, char *buf, uint buflen);
+-void dhd_iscan_lock(void);
+-void dhd_iscan_unlock(void);
+-
+-/* Packet alignment for most efficient SDIO (can change based on platform) */
+-#ifndef DHD_SDALIGN
+-#define DHD_SDALIGN 32
+-#endif
+-#if !ISPOWEROF2(DHD_SDALIGN)
+-#error DHD_SDALIGN is not a power of 2!
+-#endif
+-
+-#define EPI_VERSION_STR "4.218.248.5"
+-#ifdef DHD_DEBUG
+-const char dhd_version[] =
+-"Dongle Host Driver, version " EPI_VERSION_STR "\nCompiled on " __DATE__
+-" at " __TIME__;
+-#else
+-const char dhd_version[] = "Dongle Host Driver, version " EPI_VERSION_STR;
+-#endif
+-
+-void dhd_set_timer(void *bus, uint wdtick);
+-
+-/* IOVar table */
+-enum {
+- IOV_VERSION = 1,
+- IOV_MSGLEVEL,
+- IOV_BCMERRORSTR,
+- IOV_BCMERROR,
+- IOV_WDTICK,
+- IOV_DUMP,
+-#ifdef DHD_DEBUG
+- IOV_CONS,
+- IOV_DCONSOLE_POLL,
+-#endif
+- IOV_CLEARCOUNTS,
+- IOV_LOGDUMP,
+- IOV_LOGCAL,
+- IOV_LOGSTAMP,
+- IOV_GPIOOB,
+- IOV_IOCTLTIMEOUT,
+- IOV_LAST
+-};
+-
+-const bcm_iovar_t dhd_iovars[] = {
+- {"version", IOV_VERSION, 0, IOVT_BUFFER, sizeof(dhd_version)}
+- ,
+-#ifdef DHD_DEBUG
+- {"msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0}
+- ,
+-#endif /* DHD_DEBUG */
+- {"bcmerrorstr", IOV_BCMERRORSTR, 0, IOVT_BUFFER, BCME_STRLEN}
+- ,
+- {"bcmerror", IOV_BCMERROR, 0, IOVT_INT8, 0}
+- ,
+- {"wdtick", IOV_WDTICK, 0, IOVT_UINT32, 0}
+- ,
+- {"dump", IOV_DUMP, 0, IOVT_BUFFER, DHD_IOCTL_MAXLEN}
+- ,
+-#ifdef DHD_DEBUG
+- {"dconpoll", IOV_DCONSOLE_POLL, 0, IOVT_UINT32, 0}
+- ,
+- {"cons", IOV_CONS, 0, IOVT_BUFFER, 0}
+- ,
+-#endif
+- {"clearcounts", IOV_CLEARCOUNTS, 0, IOVT_VOID, 0}
+- ,
+- {"gpioob", IOV_GPIOOB, 0, IOVT_UINT32, 0}
+- ,
+- {"ioctl_timeout", IOV_IOCTLTIMEOUT, 0, IOVT_UINT32, 0}
+- ,
+- {NULL, 0, 0, 0, 0}
+-};
+-
+-void dhd_common_init(void)
+-{
+- /* Init global variables at run-time, not as part of the declaration.
+- * This is required to support init/de-init of the driver.
+- * Initialization
+- * of globals as part of the declaration results in non-deterministic
+- * behaviour since the value of the globals may be different on the
+- * first time that the driver is initialized vs subsequent
+- * initializations.
+- */
+- dhd_msg_level = DHD_ERROR_VAL;
+-#ifdef CONFIG_BCM4329_FW_PATH
+- strncpy(fw_path, CONFIG_BCM4329_FW_PATH, MOD_PARAM_PATHLEN - 1);
+-#else
+- fw_path[0] = '\0';
+-#endif
+-#ifdef CONFIG_BCM4329_NVRAM_PATH
+- strncpy(nv_path, CONFIG_BCM4329_NVRAM_PATH, MOD_PARAM_PATHLEN - 1);
+-#else
+- nv_path[0] = '\0';
+-#endif
+-}
+-
+-static int dhd_dump(dhd_pub_t *dhdp, char *buf, int buflen)
+-{
+- struct bcmstrbuf b;
+- struct bcmstrbuf *strbuf = &b;
+-
+- bcm_binit(strbuf, buf, buflen);
+-
+- /* Base DHD info */
+- bcm_bprintf(strbuf, "%s\n", dhd_version);
+- bcm_bprintf(strbuf, "\n");
+- bcm_bprintf(strbuf, "pub.up %d pub.txoff %d pub.busstate %d\n",
+- dhdp->up, dhdp->txoff, dhdp->busstate);
+- bcm_bprintf(strbuf, "pub.hdrlen %d pub.maxctl %d pub.rxsz %d\n",
+- dhdp->hdrlen, dhdp->maxctl, dhdp->rxsz);
+- bcm_bprintf(strbuf, "pub.iswl %d pub.drv_version %ld pub.mac %pM\n",
+- dhdp->iswl, dhdp->drv_version, &dhdp->mac);
+- bcm_bprintf(strbuf, "pub.bcmerror %d tickcnt %d\n", dhdp->bcmerror,
+- dhdp->tickcnt);
+-
+- bcm_bprintf(strbuf, "dongle stats:\n");
+- bcm_bprintf(strbuf,
+- "tx_packets %ld tx_bytes %ld tx_errors %ld tx_dropped %ld\n",
+- dhdp->dstats.tx_packets, dhdp->dstats.tx_bytes,
+- dhdp->dstats.tx_errors, dhdp->dstats.tx_dropped);
+- bcm_bprintf(strbuf,
+- "rx_packets %ld rx_bytes %ld rx_errors %ld rx_dropped %ld\n",
+- dhdp->dstats.rx_packets, dhdp->dstats.rx_bytes,
+- dhdp->dstats.rx_errors, dhdp->dstats.rx_dropped);
+- bcm_bprintf(strbuf, "multicast %ld\n", dhdp->dstats.multicast);
+-
+- bcm_bprintf(strbuf, "bus stats:\n");
+- bcm_bprintf(strbuf, "tx_packets %ld tx_multicast %ld tx_errors %ld\n",
+- dhdp->tx_packets, dhdp->tx_multicast, dhdp->tx_errors);
+- bcm_bprintf(strbuf, "tx_ctlpkts %ld tx_ctlerrs %ld\n",
+- dhdp->tx_ctlpkts, dhdp->tx_ctlerrs);
+- bcm_bprintf(strbuf, "rx_packets %ld rx_multicast %ld rx_errors %ld\n",
+- dhdp->rx_packets, dhdp->rx_multicast, dhdp->rx_errors);
+- bcm_bprintf(strbuf,
+- "rx_ctlpkts %ld rx_ctlerrs %ld rx_dropped %ld rx_flushed %ld\n",
+- dhdp->rx_ctlpkts, dhdp->rx_ctlerrs, dhdp->rx_dropped,
+- dhdp->rx_flushed);
+- bcm_bprintf(strbuf,
+- "rx_readahead_cnt %ld tx_realloc %ld fc_packets %ld\n",
+- dhdp->rx_readahead_cnt, dhdp->tx_realloc, dhdp->fc_packets);
+- bcm_bprintf(strbuf, "wd_dpc_sched %ld\n", dhdp->wd_dpc_sched);
+- bcm_bprintf(strbuf, "\n");
+-
+- /* Add any prot info */
+- dhd_prot_dump(dhdp, strbuf);
+- bcm_bprintf(strbuf, "\n");
+-
+- /* Add any bus info */
+- dhd_bus_dump(dhdp, strbuf);
+-
+- return !strbuf->size ? -EOVERFLOW : 0;
+-}
+-
+-static int
+-dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, u32 actionid,
+- const char *name, void *params, int plen, void *arg, int len,
+- int val_size)
+-{
+- int bcmerror = 0;
+- s32 int_val = 0;
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- bcmerror = bcm_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid));
+- if (bcmerror != 0)
+- goto exit;
+-
+- if (plen >= (int)sizeof(int_val))
+- memcpy(&int_val, params, sizeof(int_val));
+-
+- switch (actionid) {
+- case IOV_GVAL(IOV_VERSION):
+- /* Need to have checked buffer length */
+- strncpy((char *)arg, dhd_version, len);
+- break;
+-
+- case IOV_GVAL(IOV_MSGLEVEL):
+- int_val = (s32) dhd_msg_level;
+- memcpy(arg, &int_val, val_size);
+- break;
+-
+- case IOV_SVAL(IOV_MSGLEVEL):
+- dhd_msg_level = int_val;
+- break;
+-
+- case IOV_GVAL(IOV_BCMERRORSTR):
+- strncpy((char *)arg, "bcm_error",
+- BCME_STRLEN);
+- ((char *)arg)[BCME_STRLEN - 1] = 0x00;
+- break;
+-
+- case IOV_GVAL(IOV_BCMERROR):
+- int_val = (s32) dhd_pub->bcmerror;
+- memcpy(arg, &int_val, val_size);
+- break;
+-
+- case IOV_GVAL(IOV_WDTICK):
+- int_val = (s32) dhd_watchdog_ms;
+- memcpy(arg, &int_val, val_size);
+- break;
+-
+- case IOV_SVAL(IOV_WDTICK):
+- if (!dhd_pub->up) {
+- bcmerror = -ENOLINK;
+- break;
+- }
+- dhd_os_wd_timer(dhd_pub, (uint) int_val);
+- break;
+-
+- case IOV_GVAL(IOV_DUMP):
+- bcmerror = dhd_dump(dhd_pub, arg, len);
+- break;
+-
+-#ifdef DHD_DEBUG
+- case IOV_GVAL(IOV_DCONSOLE_POLL):
+- int_val = (s32) dhd_console_ms;
+- memcpy(arg, &int_val, val_size);
+- break;
+-
+- case IOV_SVAL(IOV_DCONSOLE_POLL):
+- dhd_console_ms = (uint) int_val;
+- break;
+-
+- case IOV_SVAL(IOV_CONS):
+- if (len > 0)
+- bcmerror = dhd_bus_console_in(dhd_pub, arg, len - 1);
+- break;
+-#endif
+-
+- case IOV_SVAL(IOV_CLEARCOUNTS):
+- dhd_pub->tx_packets = dhd_pub->rx_packets = 0;
+- dhd_pub->tx_errors = dhd_pub->rx_errors = 0;
+- dhd_pub->tx_ctlpkts = dhd_pub->rx_ctlpkts = 0;
+- dhd_pub->tx_ctlerrs = dhd_pub->rx_ctlerrs = 0;
+- dhd_pub->rx_dropped = 0;
+- dhd_pub->rx_readahead_cnt = 0;
+- dhd_pub->tx_realloc = 0;
+- dhd_pub->wd_dpc_sched = 0;
+- memset(&dhd_pub->dstats, 0, sizeof(dhd_pub->dstats));
+- dhd_bus_clearcounts(dhd_pub);
+- break;
+-
+- case IOV_GVAL(IOV_IOCTLTIMEOUT):{
+- int_val = (s32) dhd_os_get_ioctl_resp_timeout();
+- memcpy(arg, &int_val, sizeof(int_val));
+- break;
+- }
+-
+- case IOV_SVAL(IOV_IOCTLTIMEOUT):{
+- if (int_val <= 0)
+- bcmerror = -EINVAL;
+- else
+- dhd_os_set_ioctl_resp_timeout((unsigned int)
+- int_val);
+- break;
+- }
+-
+- default:
+- bcmerror = -ENOTSUPP;
+- break;
+- }
+-
+-exit:
+- return bcmerror;
+-}
+-
+-bool dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q, struct sk_buff *pkt,
+- int prec)
+-{
+- struct sk_buff *p;
+- int eprec = -1; /* precedence to evict from */
+- bool discard_oldest;
+-
+- /* Fast case, precedence queue is not full and we are also not
+- * exceeding total queue length
+- */
+- if (!pktq_pfull(q, prec) && !pktq_full(q)) {
+- bcm_pktq_penq(q, prec, pkt);
+- return true;
+- }
+-
+- /* Determine precedence from which to evict packet, if any */
+- if (pktq_pfull(q, prec))
+- eprec = prec;
+- else if (pktq_full(q)) {
+- p = bcm_pktq_peek_tail(q, &eprec);
+- ASSERT(p);
+- if (eprec > prec)
+- return false;
+- }
+-
+- /* Evict if needed */
+- if (eprec >= 0) {
+- /* Detect queueing to unconfigured precedence */
+- ASSERT(!pktq_pempty(q, eprec));
+- discard_oldest = AC_BITMAP_TST(dhdp->wme_dp, eprec);
+- if (eprec == prec && !discard_oldest)
+- return false; /* refuse newer (incoming) packet */
+- /* Evict packet according to discard policy */
+- p = discard_oldest ? bcm_pktq_pdeq(q, eprec) :
+- bcm_pktq_pdeq_tail(q, eprec);
+- if (p == NULL) {
+- DHD_ERROR(("%s: bcm_pktq_penq() failed, oldest %d.",
+- __func__, discard_oldest));
+- ASSERT(p);
+- }
+-
+- bcm_pkt_buf_free_skb(p);
+- }
+-
+- /* Enqueue */
+- p = bcm_pktq_penq(q, prec, pkt);
+- if (p == NULL) {
+- DHD_ERROR(("%s: bcm_pktq_penq() failed.", __func__));
+- ASSERT(p);
+- }
+-
+- return true;
+-}
+-
+-static int
+-dhd_iovar_op(dhd_pub_t *dhd_pub, const char *name,
+- void *params, int plen, void *arg, int len, bool set)
+-{
+- int bcmerror = 0;
+- int val_size;
+- const bcm_iovar_t *vi = NULL;
+- u32 actionid;
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- ASSERT(name);
+- ASSERT(len >= 0);
+-
+- /* Get MUST have return space */
+- ASSERT(set || (arg && len));
+-
+- /* Set does NOT take qualifiers */
+- ASSERT(!set || (!params && !plen));
+-
+- vi = bcm_iovar_lookup(dhd_iovars, name);
+- if (vi == NULL) {
+- bcmerror = -ENOTSUPP;
+- goto exit;
+- }
+-
+- DHD_CTL(("%s: %s %s, len %d plen %d\n", __func__,
+- name, (set ? "set" : "get"), len, plen));
+-
+- /* set up 'params' pointer in case this is a set command so that
+- * the convenience int and bool code can be common to set and get
+- */
+- if (params == NULL) {
+- params = arg;
+- plen = len;
+- }
+-
+- if (vi->type == IOVT_VOID)
+- val_size = 0;
+- else if (vi->type == IOVT_BUFFER)
+- val_size = len;
+- else
+- /* all other types are integer sized */
+- val_size = sizeof(int);
+-
+- actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
+- bcmerror =
+- dhd_doiovar(dhd_pub, vi, actionid, name, params, plen, arg, len,
+- val_size);
+-
+-exit:
+- return bcmerror;
+-}
+-
+-int dhd_ioctl(dhd_pub_t *dhd_pub, dhd_ioctl_t *ioc, void *buf, uint buflen)
+-{
+- int bcmerror = 0;
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- if (!buf)
+- return -EINVAL;
+-
+- switch (ioc->cmd) {
+- case DHD_GET_MAGIC:
+- if (buflen < sizeof(int))
+- bcmerror = -EOVERFLOW;
+- else
+- *(int *)buf = DHD_IOCTL_MAGIC;
+- break;
+-
+- case DHD_GET_VERSION:
+- if (buflen < sizeof(int))
+- bcmerror = -EOVERFLOW;
+- else
+- *(int *)buf = DHD_IOCTL_VERSION;
+- break;
+-
+- case DHD_GET_VAR:
+- case DHD_SET_VAR:{
+- char *arg;
+- uint arglen;
+-
+- /* scan past the name to any arguments */
+- for (arg = buf, arglen = buflen; *arg && arglen;
+- arg++, arglen--)
+- ;
+-
+- if (*arg) {
+- bcmerror = -EOVERFLOW;
+- break;
+- }
+-
+- /* account for the NUL terminator */
+- arg++, arglen--;
+-
+- /* call with the appropriate arguments */
+- if (ioc->cmd == DHD_GET_VAR)
+- bcmerror =
+- dhd_iovar_op(dhd_pub, buf, arg, arglen, buf,
+- buflen, IOV_GET);
+- else
+- bcmerror =
+- dhd_iovar_op(dhd_pub, buf, NULL, 0, arg,
+- arglen, IOV_SET);
+- if (bcmerror != -ENOTSUPP)
+- break;
+-
+- /* not in generic table, try protocol module */
+- if (ioc->cmd == DHD_GET_VAR)
+- bcmerror = dhd_prot_iovar_op(dhd_pub, buf, arg,
+- arglen, buf,
+- buflen, IOV_GET);
+- else
+- bcmerror = dhd_prot_iovar_op(dhd_pub, buf,
+- NULL, 0, arg,
+- arglen, IOV_SET);
+- if (bcmerror != -ENOTSUPP)
+- break;
+-
+- /* if still not found, try bus module */
+- if (ioc->cmd == DHD_GET_VAR)
+- bcmerror = dhd_bus_iovar_op(dhd_pub, buf,
+- arg, arglen, buf,
+- buflen, IOV_GET);
+- else
+- bcmerror = dhd_bus_iovar_op(dhd_pub, buf,
+- NULL, 0, arg,
+- arglen, IOV_SET);
+-
+- break;
+- }
+-
+- default:
+- bcmerror = -ENOTSUPP;
+- }
+-
+- return bcmerror;
+-}
+-
+-#ifdef SHOW_EVENTS
+-static void wl_show_host_event(wl_event_msg_t *event, void *event_data)
+-{
+- uint i, status, reason;
+- bool group = false, flush_txq = false, link = false;
+- char *auth_str, *event_name;
+- unsigned char *buf;
+- char err_msg[256], eabuf[ETHER_ADDR_STR_LEN];
+- static struct {
+- uint event;
+- char *event_name;
+- } event_names[] = {
+- {
+- WLC_E_SET_SSID, "SET_SSID"}, {
+- WLC_E_JOIN, "JOIN"}, {
+- WLC_E_START, "START"}, {
+- WLC_E_AUTH, "AUTH"}, {
+- WLC_E_AUTH_IND, "AUTH_IND"}, {
+- WLC_E_DEAUTH, "DEAUTH"}, {
+- WLC_E_DEAUTH_IND, "DEAUTH_IND"}, {
+- WLC_E_ASSOC, "ASSOC"}, {
+- WLC_E_ASSOC_IND, "ASSOC_IND"}, {
+- WLC_E_REASSOC, "REASSOC"}, {
+- WLC_E_REASSOC_IND, "REASSOC_IND"}, {
+- WLC_E_DISASSOC, "DISASSOC"}, {
+- WLC_E_DISASSOC_IND, "DISASSOC_IND"}, {
+- WLC_E_QUIET_START, "START_QUIET"}, {
+- WLC_E_QUIET_END, "END_QUIET"}, {
+- WLC_E_BEACON_RX, "BEACON_RX"}, {
+- WLC_E_LINK, "LINK"}, {
+- WLC_E_MIC_ERROR, "MIC_ERROR"}, {
+- WLC_E_NDIS_LINK, "NDIS_LINK"}, {
+- WLC_E_ROAM, "ROAM"}, {
+- WLC_E_TXFAIL, "TXFAIL"}, {
+- WLC_E_PMKID_CACHE, "PMKID_CACHE"}, {
+- WLC_E_RETROGRADE_TSF, "RETROGRADE_TSF"}, {
+- WLC_E_PRUNE, "PRUNE"}, {
+- WLC_E_AUTOAUTH, "AUTOAUTH"}, {
+- WLC_E_EAPOL_MSG, "EAPOL_MSG"}, {
+- WLC_E_SCAN_COMPLETE, "SCAN_COMPLETE"}, {
+- WLC_E_ADDTS_IND, "ADDTS_IND"}, {
+- WLC_E_DELTS_IND, "DELTS_IND"}, {
+- WLC_E_BCNSENT_IND, "BCNSENT_IND"}, {
+- WLC_E_BCNRX_MSG, "BCNRX_MSG"}, {
+- WLC_E_BCNLOST_MSG, "BCNLOST_MSG"}, {
+- WLC_E_ROAM_PREP, "ROAM_PREP"}, {
+- WLC_E_PFN_NET_FOUND, "PNO_NET_FOUND"}, {
+- WLC_E_PFN_NET_LOST, "PNO_NET_LOST"}, {
+- WLC_E_RESET_COMPLETE, "RESET_COMPLETE"}, {
+- WLC_E_JOIN_START, "JOIN_START"}, {
+- WLC_E_ROAM_START, "ROAM_START"}, {
+- WLC_E_ASSOC_START, "ASSOC_START"}, {
+- WLC_E_IBSS_ASSOC, "IBSS_ASSOC"}, {
+- WLC_E_RADIO, "RADIO"}, {
+- WLC_E_PSM_WATCHDOG, "PSM_WATCHDOG"}, {
+- WLC_E_PROBREQ_MSG, "PROBREQ_MSG"}, {
+- WLC_E_SCAN_CONFIRM_IND, "SCAN_CONFIRM_IND"}, {
+- WLC_E_PSK_SUP, "PSK_SUP"}, {
+- WLC_E_COUNTRY_CODE_CHANGED, "COUNTRY_CODE_CHANGED"}, {
+- WLC_E_EXCEEDED_MEDIUM_TIME, "EXCEEDED_MEDIUM_TIME"}, {
+- WLC_E_ICV_ERROR, "ICV_ERROR"}, {
+- WLC_E_UNICAST_DECODE_ERROR, "UNICAST_DECODE_ERROR"}, {
+- WLC_E_MULTICAST_DECODE_ERROR, "MULTICAST_DECODE_ERROR"}, {
+- WLC_E_TRACE, "TRACE"}, {
+- WLC_E_ACTION_FRAME, "ACTION FRAME"}, {
+- WLC_E_ACTION_FRAME_COMPLETE, "ACTION FRAME TX COMPLETE"}, {
+- WLC_E_IF, "IF"}, {
+- WLC_E_RSSI, "RSSI"}, {
+- WLC_E_PFN_SCAN_COMPLETE, "SCAN_COMPLETE"}
+- };
+- uint event_type, flags, auth_type, datalen;
+- event_type = be32_to_cpu(event->event_type);
+- flags = be16_to_cpu(event->flags);
+- status = be32_to_cpu(event->status);
+- reason = be32_to_cpu(event->reason);
+- auth_type = be32_to_cpu(event->auth_type);
+- datalen = be32_to_cpu(event->datalen);
+- /* debug dump of event messages */
+- sprintf(eabuf, "%pM", event->addr);
+-
+- event_name = "UNKNOWN";
+- for (i = 0; i < ARRAY_SIZE(event_names); i++) {
+- if (event_names[i].event == event_type)
+- event_name = event_names[i].event_name;
+- }
+-
+- DHD_EVENT(("EVENT: %s, event ID = %d\n", event_name, event_type));
+- DHD_EVENT(("flags 0x%04x, status %d, reason %d, auth_type %d MAC %s\n",
+- flags, status, reason, auth_type, eabuf));
+-
+- if (flags & WLC_EVENT_MSG_LINK)
+- link = true;
+- if (flags & WLC_EVENT_MSG_GROUP)
+- group = true;
+- if (flags & WLC_EVENT_MSG_FLUSHTXQ)
+- flush_txq = true;
+-
+- switch (event_type) {
+- case WLC_E_START:
+- case WLC_E_DEAUTH:
+- case WLC_E_DISASSOC:
+- DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
+- break;
+-
+- case WLC_E_ASSOC_IND:
+- case WLC_E_REASSOC_IND:
+- DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
+- break;
+-
+- case WLC_E_ASSOC:
+- case WLC_E_REASSOC:
+- if (status == WLC_E_STATUS_SUCCESS) {
+- DHD_EVENT(("MACEVENT: %s, MAC %s, SUCCESS\n",
+- event_name, eabuf));
+- } else if (status == WLC_E_STATUS_TIMEOUT) {
+- DHD_EVENT(("MACEVENT: %s, MAC %s, TIMEOUT\n",
+- event_name, eabuf));
+- } else if (status == WLC_E_STATUS_FAIL) {
+- DHD_EVENT(("MACEVENT: %s, MAC %s, FAILURE, reason %d\n",
+- event_name, eabuf, (int)reason));
+- } else {
+- DHD_EVENT(("MACEVENT: %s, MAC %s, unexpected status "
+- "%d\n", event_name, eabuf, (int)status));
+- }
+- break;
+-
+- case WLC_E_DEAUTH_IND:
+- case WLC_E_DISASSOC_IND:
+- DHD_EVENT(("MACEVENT: %s, MAC %s, reason %d\n", event_name,
+- eabuf, (int)reason));
+- break;
+-
+- case WLC_E_AUTH:
+- case WLC_E_AUTH_IND:
+- if (auth_type == WLAN_AUTH_OPEN)
+- auth_str = "Open System";
+- else if (auth_type == WLAN_AUTH_SHARED_KEY)
+- auth_str = "Shared Key";
+- else {
+- sprintf(err_msg, "AUTH unknown: %d", (int)auth_type);
+- auth_str = err_msg;
+- }
+- if (event_type == WLC_E_AUTH_IND) {
+- DHD_EVENT(("MACEVENT: %s, MAC %s, %s\n", event_name,
+- eabuf, auth_str));
+- } else if (status == WLC_E_STATUS_SUCCESS) {
+- DHD_EVENT(("MACEVENT: %s, MAC %s, %s, SUCCESS\n",
+- event_name, eabuf, auth_str));
+- } else if (status == WLC_E_STATUS_TIMEOUT) {
+- DHD_EVENT(("MACEVENT: %s, MAC %s, %s, TIMEOUT\n",
+- event_name, eabuf, auth_str));
+- } else if (status == WLC_E_STATUS_FAIL) {
+- DHD_EVENT(("MACEVENT: %s, MAC %s, %s, FAILURE, "
+- "reason %d\n",
+- event_name, eabuf, auth_str, (int)reason));
+- }
+-
+- break;
+-
+- case WLC_E_JOIN:
+- case WLC_E_ROAM:
+- case WLC_E_SET_SSID:
+- if (status == WLC_E_STATUS_SUCCESS) {
+- DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name,
+- eabuf));
+- } else if (status == WLC_E_STATUS_FAIL) {
+- DHD_EVENT(("MACEVENT: %s, failed\n", event_name));
+- } else if (status == WLC_E_STATUS_NO_NETWORKS) {
+- DHD_EVENT(("MACEVENT: %s, no networks found\n",
+- event_name));
+- } else {
+- DHD_EVENT(("MACEVENT: %s, unexpected status %d\n",
+- event_name, (int)status));
+- }
+- break;
+-
+- case WLC_E_BEACON_RX:
+- if (status == WLC_E_STATUS_SUCCESS) {
+- DHD_EVENT(("MACEVENT: %s, SUCCESS\n", event_name));
+- } else if (status == WLC_E_STATUS_FAIL) {
+- DHD_EVENT(("MACEVENT: %s, FAIL\n", event_name));
+- } else {
+- DHD_EVENT(("MACEVENT: %s, status %d\n", event_name,
+- status));
+- }
+- break;
+-
+- case WLC_E_LINK:
+- DHD_EVENT(("MACEVENT: %s %s\n", event_name,
+- link ? "UP" : "DOWN"));
+- break;
+-
+- case WLC_E_MIC_ERROR:
+- DHD_EVENT(("MACEVENT: %s, MAC %s, Group %d, Flush %d\n",
+- event_name, eabuf, group, flush_txq));
+- break;
+-
+- case WLC_E_ICV_ERROR:
+- case WLC_E_UNICAST_DECODE_ERROR:
+- case WLC_E_MULTICAST_DECODE_ERROR:
+- DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf));
+- break;
+-
+- case WLC_E_TXFAIL:
+- DHD_EVENT(("MACEVENT: %s, RA %s\n", event_name, eabuf));
+- break;
+-
+- case WLC_E_SCAN_COMPLETE:
+- case WLC_E_PMKID_CACHE:
+- DHD_EVENT(("MACEVENT: %s\n", event_name));
+- break;
+-
+- case WLC_E_PFN_NET_FOUND:
+- case WLC_E_PFN_NET_LOST:
+- case WLC_E_PFN_SCAN_COMPLETE:
+- DHD_EVENT(("PNOEVENT: %s\n", event_name));
+- break;
+-
+- case WLC_E_PSK_SUP:
+- case WLC_E_PRUNE:
+- DHD_EVENT(("MACEVENT: %s, status %d, reason %d\n",
+- event_name, (int)status, (int)reason));
+- break;
+-
+- case WLC_E_TRACE:
+- {
+- static u32 seqnum_prev;
+- msgtrace_hdr_t hdr;
+- u32 nblost;
+- char *s, *p;
+-
+- buf = (unsigned char *) event_data;
+- memcpy(&hdr, buf, MSGTRACE_HDRLEN);
+-
+- if (hdr.version != MSGTRACE_VERSION) {
+- DHD_ERROR(
+- ("\nMACEVENT: %s [unsupported version --> "
+- "dhd version:%d dongle version:%d]\n",
+- event_name, MSGTRACE_VERSION, hdr.version)
+- );
+- /* Reset datalen to avoid display below */
+- datalen = 0;
+- break;
+- }
+-
+- /* There are 2 bytes available at the end of data */
+- buf[MSGTRACE_HDRLEN + be16_to_cpu(hdr.len)] = '\0';
+-
+- if (be32_to_cpu(hdr.discarded_bytes)
+- || be32_to_cpu(hdr.discarded_printf)) {
+- DHD_ERROR(
+- ("\nWLC_E_TRACE: [Discarded traces in dongle -->"
+- "discarded_bytes %d discarded_printf %d]\n",
+- be32_to_cpu(hdr.discarded_bytes),
+- be32_to_cpu(hdr.discarded_printf)));
+- }
+-
+- nblost = be32_to_cpu(hdr.seqnum) - seqnum_prev - 1;
+- if (nblost > 0) {
+- DHD_ERROR(
+- ("\nWLC_E_TRACE: [Event lost --> seqnum %d nblost %d\n",
+- be32_to_cpu(hdr.seqnum), nblost));
+- }
+- seqnum_prev = be32_to_cpu(hdr.seqnum);
+-
+- /* Display the trace buffer. Advance from \n to \n to
+- * avoid display big
+- * printf (issue with Linux printk )
+- */
+- p = (char *)&buf[MSGTRACE_HDRLEN];
+- while ((s = strstr(p, "\n")) != NULL) {
+- *s = '\0';
+- printk(KERN_DEBUG"%s\n", p);
+- p = s + 1;
+- }
+- printk(KERN_DEBUG "%s\n", p);
+-
+- /* Reset datalen to avoid display below */
+- datalen = 0;
+- }
+- break;
+-
+- case WLC_E_RSSI:
+- DHD_EVENT(("MACEVENT: %s %d\n", event_name,
+- be32_to_cpu(*((int *)event_data))));
+- break;
+-
+- default:
+- DHD_EVENT(("MACEVENT: %s %d, MAC %s, status %d, reason %d, "
+- "auth %d\n", event_name, event_type, eabuf,
+- (int)status, (int)reason, (int)auth_type));
+- break;
+- }
+-
+- /* show any appended data */
+- if (datalen) {
+- buf = (unsigned char *) event_data;
+- DHD_EVENT((" data (%d) : ", datalen));
+- for (i = 0; i < datalen; i++)
+- DHD_EVENT((" 0x%02x ", *buf++));
+- DHD_EVENT(("\n"));
+- }
+-}
+-#endif /* SHOW_EVENTS */
+-
+-int
+-wl_host_event(struct dhd_info *dhd, int *ifidx, void *pktdata,
+- wl_event_msg_t *event, void **data_ptr)
+-{
+- /* check whether packet is a BRCM event pkt */
+- bcm_event_t *pvt_data = (bcm_event_t *) pktdata;
+- char *event_data;
+- u32 type, status;
+- u16 flags;
+- int evlen;
+-
+- if (memcmp(BRCM_OUI, &pvt_data->bcm_hdr.oui[0], DOT11_OUI_LEN)) {
+- DHD_ERROR(("%s: mismatched OUI, bailing\n", __func__));
+- return -EBADE;
+- }
+-
+- /* BRCM event pkt may be unaligned - use xxx_ua to load user_subtype. */
+- if (get_unaligned_be16(&pvt_data->bcm_hdr.usr_subtype) !=
+- BCMILCP_BCM_SUBTYPE_EVENT) {
+- DHD_ERROR(("%s: mismatched subtype, bailing\n", __func__));
+- return -EBADE;
+- }
+-
+- *data_ptr = &pvt_data[1];
+- event_data = *data_ptr;
+-
+- /* memcpy since BRCM event pkt may be unaligned. */
+- memcpy(event, &pvt_data->event, sizeof(wl_event_msg_t));
+-
+- type = get_unaligned_be32(&event->event_type);
+- flags = get_unaligned_be16(&event->flags);
+- status = get_unaligned_be32(&event->status);
+- evlen = get_unaligned_be32(&event->datalen) + sizeof(bcm_event_t);
+-
+- switch (type) {
+- case WLC_E_IF:
+- {
+- dhd_if_event_t *ifevent = (dhd_if_event_t *) event_data;
+- DHD_TRACE(("%s: if event\n", __func__));
+-
+- if (ifevent->ifidx > 0 &&
+- ifevent->ifidx < DHD_MAX_IFS) {
+- if (ifevent->action == WLC_E_IF_ADD)
+- dhd_add_if(dhd, ifevent->ifidx,
+- NULL, event->ifname,
+- pvt_data->eth.h_dest,
+- ifevent->flags,
+- ifevent->bssidx);
+- else
+- dhd_del_if(dhd, ifevent->ifidx);
+- } else {
+- DHD_ERROR(("%s: Invalid ifidx %d for %s\n",
+- __func__, ifevent->ifidx,
+- event->ifname));
+- }
+- }
+- /* send up the if event: btamp user needs it */
+- *ifidx = dhd_ifname2idx(dhd, event->ifname);
+- /* push up to external supp/auth */
+- dhd_event(dhd, (char *)pvt_data, evlen, *ifidx);
+- break;
+-
+-#ifdef P2P
+- case WLC_E_NDIS_LINK:
+- break;
+-#endif
+- /* fall through */
+- /* These are what external supplicant/authenticator wants */
+- case WLC_E_LINK:
+- case WLC_E_ASSOC_IND:
+- case WLC_E_REASSOC_IND:
+- case WLC_E_DISASSOC_IND:
+- case WLC_E_MIC_ERROR:
+- default:
+- /* Fall through: this should get _everything_ */
+-
+- *ifidx = dhd_ifname2idx(dhd, event->ifname);
+- /* push up to external supp/auth */
+- dhd_event(dhd, (char *)pvt_data, evlen, *ifidx);
+- DHD_TRACE(("%s: MAC event %d, flags %x, status %x\n",
+- __func__, type, flags, status));
+-
+- /* put it back to WLC_E_NDIS_LINK */
+- if (type == WLC_E_NDIS_LINK) {
+- u32 temp;
+-
+- temp = get_unaligned_be32(&event->event_type);
+- DHD_TRACE(("Converted to WLC_E_LINK type %d\n", temp));
+-
+- temp = be32_to_cpu(WLC_E_NDIS_LINK);
+- memcpy((void *)(&pvt_data->event.event_type), &temp,
+- sizeof(pvt_data->event.event_type));
+- }
+- break;
+- }
+-
+-#ifdef SHOW_EVENTS
+- wl_show_host_event(event, event_data);
+-#endif /* SHOW_EVENTS */
+-
+- return 0;
+-}
+-
+-/* Convert user's input in hex pattern to byte-size mask */
+-static int wl_pattern_atoh(char *src, char *dst)
+-{
+- int i;
+- if (strncmp(src, "0x", 2) != 0 && strncmp(src, "0X", 2) != 0) {
+- DHD_ERROR(("Mask invalid format. Needs to start with 0x\n"));
+- return -1;
+- }
+- src = src + 2; /* Skip past 0x */
+- if (strlen(src) % 2 != 0) {
+- DHD_ERROR(("Mask invalid format. Length must be even.\n"));
+- return -1;
+- }
+- for (i = 0; *src != '\0'; i++) {
+- char num[3];
+- strncpy(num, src, 2);
+- num[2] = '\0';
+- dst[i] = (u8) simple_strtoul(num, NULL, 16);
+- src += 2;
+- }
+- return i;
+-}
+-
+-void
+-dhd_pktfilter_offload_enable(dhd_pub_t *dhd, char *arg, int enable,
+- int master_mode)
+-{
+- char *argv[8];
+- int i = 0;
+- const char *str;
+- int buf_len;
+- int str_len;
+- char *arg_save = 0, *arg_org = 0;
+- int rc;
+- char buf[128];
+- wl_pkt_filter_enable_t enable_parm;
+- wl_pkt_filter_enable_t *pkt_filterp;
+-
+- arg_save = kmalloc(strlen(arg) + 1, GFP_ATOMIC);
+- if (!arg_save) {
+- DHD_ERROR(("%s: kmalloc failed\n", __func__));
+- goto fail;
+- }
+- arg_org = arg_save;
+- memcpy(arg_save, arg, strlen(arg) + 1);
+-
+- argv[i] = strsep(&arg_save, " ");
+-
+- i = 0;
+- if (NULL == argv[i]) {
+- DHD_ERROR(("No args provided\n"));
+- goto fail;
+- }
+-
+- str = "pkt_filter_enable";
+- str_len = strlen(str);
+- strncpy(buf, str, str_len);
+- buf[str_len] = '\0';
+- buf_len = str_len + 1;
+-
+- pkt_filterp = (wl_pkt_filter_enable_t *) (buf + str_len + 1);
+-
+- /* Parse packet filter id. */
+- enable_parm.id = simple_strtoul(argv[i], NULL, 0);
+-
+- /* Parse enable/disable value. */
+- enable_parm.enable = enable;
+-
+- buf_len += sizeof(enable_parm);
+- memcpy((char *)pkt_filterp, &enable_parm, sizeof(enable_parm));
+-
+- /* Enable/disable the specified filter. */
+- rc = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, buf_len);
+- rc = rc >= 0 ? 0 : rc;
+- if (rc)
+- DHD_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
+- __func__, arg, rc));
+- else
+- DHD_TRACE(("%s: successfully added pktfilter %s\n",
+- __func__, arg));
+-
+- /* Contorl the master mode */
+- bcm_mkiovar("pkt_filter_mode", (char *)&master_mode, 4, buf,
+- sizeof(buf));
+- rc = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, sizeof(buf));
+- rc = rc >= 0 ? 0 : rc;
+- if (rc)
+- DHD_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
+- __func__, arg, rc));
+-
+-fail:
+- kfree(arg_org);
+-}
+-
+-void dhd_pktfilter_offload_set(dhd_pub_t *dhd, char *arg)
+-{
+- const char *str;
+- wl_pkt_filter_t pkt_filter;
+- wl_pkt_filter_t *pkt_filterp;
+- int buf_len;
+- int str_len;
+- int rc;
+- u32 mask_size;
+- u32 pattern_size;
+- char *argv[8], *buf = 0;
+- int i = 0;
+- char *arg_save = 0, *arg_org = 0;
+-#define BUF_SIZE 2048
+-
+- arg_save = kmalloc(strlen(arg) + 1, GFP_ATOMIC);
+- if (!arg_save) {
+- DHD_ERROR(("%s: kmalloc failed\n", __func__));
+- goto fail;
+- }
+-
+- arg_org = arg_save;
+-
+- buf = kmalloc(BUF_SIZE, GFP_ATOMIC);
+- if (!buf) {
+- DHD_ERROR(("%s: kmalloc failed\n", __func__));
+- goto fail;
+- }
+-
+- memcpy(arg_save, arg, strlen(arg) + 1);
+-
+- if (strlen(arg) > BUF_SIZE) {
+- DHD_ERROR(("Not enough buffer %d < %d\n", (int)strlen(arg),
+- (int)sizeof(buf)));
+- goto fail;
+- }
+-
+- argv[i] = strsep(&arg_save, " ");
+- while (argv[i++])
+- argv[i] = strsep(&arg_save, " ");
+-
+- i = 0;
+- if (NULL == argv[i]) {
+- DHD_ERROR(("No args provided\n"));
+- goto fail;
+- }
+-
+- str = "pkt_filter_add";
+- str_len = strlen(str);
+- strncpy(buf, str, str_len);
+- buf[str_len] = '\0';
+- buf_len = str_len + 1;
+-
+- pkt_filterp = (wl_pkt_filter_t *) (buf + str_len + 1);
+-
+- /* Parse packet filter id. */
+- pkt_filter.id = simple_strtoul(argv[i], NULL, 0);
+-
+- if (NULL == argv[++i]) {
+- DHD_ERROR(("Polarity not provided\n"));
+- goto fail;
+- }
+-
+- /* Parse filter polarity. */
+- pkt_filter.negate_match = simple_strtoul(argv[i], NULL, 0);
+-
+- if (NULL == argv[++i]) {
+- DHD_ERROR(("Filter type not provided\n"));
+- goto fail;
+- }
+-
+- /* Parse filter type. */
+- pkt_filter.type = simple_strtoul(argv[i], NULL, 0);
+-
+- if (NULL == argv[++i]) {
+- DHD_ERROR(("Offset not provided\n"));
+- goto fail;
+- }
+-
+- /* Parse pattern filter offset. */
+- pkt_filter.u.pattern.offset = simple_strtoul(argv[i], NULL, 0);
+-
+- if (NULL == argv[++i]) {
+- DHD_ERROR(("Bitmask not provided\n"));
+- goto fail;
+- }
+-
+- /* Parse pattern filter mask. */
+- mask_size =
+- wl_pattern_atoh
+- (argv[i], (char *)pkt_filterp->u.pattern.mask_and_pattern);
+-
+- if (NULL == argv[++i]) {
+- DHD_ERROR(("Pattern not provided\n"));
+- goto fail;
+- }
+-
+- /* Parse pattern filter pattern. */
+- pattern_size =
+- wl_pattern_atoh(argv[i],
+- (char *)&pkt_filterp->u.pattern.
+- mask_and_pattern[mask_size]);
+-
+- if (mask_size != pattern_size) {
+- DHD_ERROR(("Mask and pattern not the same size\n"));
+- goto fail;
+- }
+-
+- pkt_filter.u.pattern.size_bytes = mask_size;
+- buf_len += WL_PKT_FILTER_FIXED_LEN;
+- buf_len += (WL_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size);
+-
+- /* Keep-alive attributes are set in local
+- * variable (keep_alive_pkt), and
+- ** then memcpy'ed into buffer (keep_alive_pktp) since there is no
+- ** guarantee that the buffer is properly aligned.
+- */
+- memcpy((char *)pkt_filterp,
+- &pkt_filter,
+- WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN);
+-
+- rc = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, buf_len);
+- rc = rc >= 0 ? 0 : rc;
+-
+- if (rc)
+- DHD_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
+- __func__, arg, rc));
+- else
+- DHD_TRACE(("%s: successfully added pktfilter %s\n",
+- __func__, arg));
+-
+-fail:
+- kfree(arg_org);
+-
+- kfree(buf);
+-}
+-
+-void dhd_arp_offload_set(dhd_pub_t *dhd, int arp_mode)
+-{
+- char iovbuf[32];
+- int retcode;
+-
+- bcm_mkiovar("arp_ol", (char *)&arp_mode, 4, iovbuf, sizeof(iovbuf));
+- retcode = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+- retcode = retcode >= 0 ? 0 : retcode;
+- if (retcode)
+- DHD_TRACE(("%s: failed to set ARP offload mode to 0x%x, "
+- "retcode = %d\n", __func__, arp_mode, retcode));
+- else
+- DHD_TRACE(("%s: successfully set ARP offload mode to 0x%x\n",
+- __func__, arp_mode));
+-}
+-
+-void dhd_arp_offload_enable(dhd_pub_t *dhd, int arp_enable)
+-{
+- char iovbuf[32];
+- int retcode;
+-
+- bcm_mkiovar("arpoe", (char *)&arp_enable, 4, iovbuf, sizeof(iovbuf));
+- retcode = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+- retcode = retcode >= 0 ? 0 : retcode;
+- if (retcode)
+- DHD_TRACE(("%s: failed to enabe ARP offload to %d, "
+- "retcode = %d\n", __func__, arp_enable, retcode));
+- else
+- DHD_TRACE(("%s: successfully enabed ARP offload to %d\n",
+- __func__, arp_enable));
+-}
+-
+-int dhd_preinit_ioctls(dhd_pub_t *dhd)
+-{
+- char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for
+- "event_msgs" + '\0' + bitvec */
+- uint up = 0;
+- char buf[128], *ptr;
+- uint power_mode = PM_FAST;
+- u32 dongle_align = DHD_SDALIGN;
+- u32 glom = 0;
+- uint bcn_timeout = 3;
+- int scan_assoc_time = 40;
+- int scan_unassoc_time = 40;
+-#ifdef GET_CUSTOM_MAC_ENABLE
+- int ret = 0;
+- u8 ea_addr[ETH_ALEN];
+-#endif /* GET_CUSTOM_MAC_ENABLE */
+-
+- dhd_os_proto_block(dhd);
+-
+-#ifdef GET_CUSTOM_MAC_ENABLE
+- /* Read MAC address from external customer place
+- ** NOTE that default mac address has to be present in
+- ** otp or nvram file to bring up
+- ** firmware but unique per board mac address maybe provided by
+- ** customer code
+- */
+- ret = dhd_custom_get_mac_address(ea_addr);
+- if (!ret) {
+- bcm_mkiovar("cur_etheraddr", (void *)ea_addr, ETH_ALEN,
+- buf, sizeof(buf));
+- ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, sizeof(buf));
+- if (ret < 0) {
+- DHD_ERROR(("%s: can't set MAC address , error=%d\n",
+- __func__, ret));
+- } else
+- memcpy(dhd->mac.octet, (void *)&ea_addr,
+- ETH_ALEN);
+- }
+-#endif /* GET_CUSTOM_MAC_ENABLE */
+-
+- /* Set Country code */
+- if (dhd->country_code[0] != 0) {
+- if (dhdcdc_set_ioctl(dhd, 0, WLC_SET_COUNTRY,
+- dhd->country_code,
+- sizeof(dhd->country_code)) < 0) {
+- DHD_ERROR(("%s: country code setting failed\n",
+- __func__));
+- }
+- }
+-
+- /* query for 'ver' to get version info from firmware */
+- memset(buf, 0, sizeof(buf));
+- ptr = buf;
+- bcm_mkiovar("ver", 0, 0, buf, sizeof(buf));
+- dhdcdc_query_ioctl(dhd, 0, WLC_GET_VAR, buf, sizeof(buf));
+- strsep(&ptr, "\n");
+- /* Print fw version info */
+- DHD_ERROR(("Firmware version = %s\n", buf));
+-
+- /* Set PowerSave mode */
+- dhdcdc_set_ioctl(dhd, 0, WLC_SET_PM, (char *)&power_mode,
+- sizeof(power_mode));
+-
+- /* Match Host and Dongle rx alignment */
+- bcm_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf,
+- sizeof(iovbuf));
+- dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+-
+- /* disable glom option per default */
+- bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf));
+- dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+-
+- /* Setup timeout if Beacons are lost and roam is off to report
+- link down */
+- bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf,
+- sizeof(iovbuf));
+- dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+-
+- /* Enable/Disable build-in roaming to allowed ext supplicant to take
+- of romaing */
+- bcm_mkiovar("roam_off", (char *)&dhd_roam, 4, iovbuf, sizeof(iovbuf));
+- dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+-
+- /* Force STA UP */
+- if (dhd_radio_up)
+- dhdcdc_set_ioctl(dhd, 0, WLC_UP, (char *)&up, sizeof(up));
+-
+- /* Setup event_msgs */
+- bcm_mkiovar("event_msgs", dhd->eventmask, WL_EVENTING_MASK_LEN, iovbuf,
+- sizeof(iovbuf));
+- dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+-
+- dhdcdc_set_ioctl(dhd, 0, WLC_SET_SCAN_CHANNEL_TIME,
+- (char *)&scan_assoc_time, sizeof(scan_assoc_time));
+- dhdcdc_set_ioctl(dhd, 0, WLC_SET_SCAN_UNASSOC_TIME,
+- (char *)&scan_unassoc_time, sizeof(scan_unassoc_time));
+-
+-#ifdef ARP_OFFLOAD_SUPPORT
+- /* Set and enable ARP offload feature */
+- if (dhd_arp_enable)
+- dhd_arp_offload_set(dhd, dhd_arp_mode);
+- dhd_arp_offload_enable(dhd, dhd_arp_enable);
+-#endif /* ARP_OFFLOAD_SUPPORT */
+-
+-#ifdef PKT_FILTER_SUPPORT
+- {
+- int i;
+- /* Set up pkt filter */
+- if (dhd_pkt_filter_enable) {
+- for (i = 0; i < dhd->pktfilter_count; i++) {
+- dhd_pktfilter_offload_set(dhd,
+- dhd->pktfilter[i]);
+- dhd_pktfilter_offload_enable(dhd,
+- dhd->pktfilter[i],
+- dhd_pkt_filter_init,
+- dhd_master_mode);
+- }
+- }
+- }
+-#endif /* PKT_FILTER_SUPPORT */
+-
+- dhd_os_proto_unblock(dhd);
+-
+- return 0;
+-}
+-
+-#ifdef SIMPLE_ISCAN
+-uint iscan_thread_id;
+-iscan_buf_t *iscan_chain;
+-
+-iscan_buf_t *dhd_iscan_allocate_buf(dhd_pub_t *dhd, iscan_buf_t **iscanbuf)
+-{
+- iscan_buf_t *iscanbuf_alloc = 0;
+- iscan_buf_t *iscanbuf_head;
+-
+- dhd_iscan_lock();
+-
+- iscanbuf_alloc = kmalloc(sizeof(iscan_buf_t), GFP_ATOMIC);
+- if (iscanbuf_alloc == NULL)
+- goto fail;
+-
+- iscanbuf_alloc->next = NULL;
+- iscanbuf_head = *iscanbuf;
+-
+- DHD_ISCAN(("%s: addr of allocated node = 0x%X"
+- "addr of iscanbuf_head = 0x%X dhd = 0x%X\n",
+- __func__, iscanbuf_alloc, iscanbuf_head, dhd));
+-
+- if (iscanbuf_head == NULL) {
+- *iscanbuf = iscanbuf_alloc;
+- DHD_ISCAN(("%s: Head is allocated\n", __func__));
+- goto fail;
+- }
+-
+- while (iscanbuf_head->next)
+- iscanbuf_head = iscanbuf_head->next;
+-
+- iscanbuf_head->next = iscanbuf_alloc;
+-
+-fail:
+- dhd_iscan_unlock();
+- return iscanbuf_alloc;
+-}
+-
+-void dhd_iscan_free_buf(void *dhdp, iscan_buf_t *iscan_delete)
+-{
+- iscan_buf_t *iscanbuf_free = 0;
+- iscan_buf_t *iscanbuf_prv = 0;
+- iscan_buf_t *iscanbuf_cur = iscan_chain;
+- dhd_pub_t *dhd = dhd_bus_pub(dhdp);
+-
+- dhd_iscan_lock();
+- /* If iscan_delete is null then delete the entire
+- * chain or else delete specific one provided
+- */
+- if (!iscan_delete) {
+- while (iscanbuf_cur) {
+- iscanbuf_free = iscanbuf_cur;
+- iscanbuf_cur = iscanbuf_cur->next;
+- iscanbuf_free->next = 0;
+- kfree(iscanbuf_free);
+- }
+- iscan_chain = 0;
+- } else {
+- while (iscanbuf_cur) {
+- if (iscanbuf_cur == iscan_delete)
+- break;
+- iscanbuf_prv = iscanbuf_cur;
+- iscanbuf_cur = iscanbuf_cur->next;
+- }
+- if (iscanbuf_prv)
+- iscanbuf_prv->next = iscan_delete->next;
+-
+- iscan_delete->next = 0;
+- kfree(iscan_delete);
+-
+- if (!iscanbuf_prv)
+- iscan_chain = 0;
+- }
+- dhd_iscan_unlock();
+-}
+-
+-iscan_buf_t *dhd_iscan_result_buf(void)
+-{
+- return iscan_chain;
+-}
+-
+-/*
+-* print scan cache
+-* print partial iscan_skip list differently
+-*/
+-int dhd_iscan_print_cache(iscan_buf_t *iscan_skip)
+-{
+- int i = 0, l = 0;
+- iscan_buf_t *iscan_cur;
+- wl_iscan_results_t *list;
+- wl_scan_results_t *results;
+- wl_bss_info_t UNALIGNED *bi;
+-
+- dhd_iscan_lock();
+-
+- iscan_cur = dhd_iscan_result_buf();
+-
+- while (iscan_cur) {
+- list = (wl_iscan_results_t *)iscan_cur->iscan_buf;
+- if (!list)
+- break;
+-
+- results = (wl_scan_results_t *)&list->results;
+- if (!results)
+- break;
+-
+- if (results->version != WL_BSS_INFO_VERSION) {
+- DHD_ISCAN(("%s: results->version %d != "
+- "WL_BSS_INFO_VERSION\n",
+- __func__, results->version));
+- goto done;
+- }
+-
+- bi = results->bss_info;
+- for (i = 0; i < results->count; i++) {
+- if (!bi)
+- break;
+-
+- DHD_ISCAN(("%s[%2.2d:%2.2d] %X:%X:%X:%X:%X:%X\n",
+- iscan_cur != iscan_skip ? "BSS" : "bss", l,
+- i, bi->BSSID.octet[0], bi->BSSID.octet[1],
+- bi->BSSID.octet[2], bi->BSSID.octet[3],
+- bi->BSSID.octet[4], bi->BSSID.octet[5]));
+-
+- bi = (wl_bss_info_t *)((unsigned long)bi + bi->length);
+- }
+- iscan_cur = iscan_cur->next;
+- l++;
+- }
+-
+-done:
+- dhd_iscan_unlock();
+- return 0;
+-}
+-
+-/*
+-* delete disappeared AP from specific scan cache but skip partial
+-* list in iscan_skip
+-*/
+-int dhd_iscan_delete_bss(void *dhdp, void *addr, iscan_buf_t *iscan_skip)
+-{
+- int i = 0, j = 0, l = 0;
+- iscan_buf_t *iscan_cur;
+- wl_iscan_results_t *list;
+- wl_scan_results_t *results;
+- wl_bss_info_t UNALIGNED *bi, *bi_new, *bi_next;
+-
+- unsigned char *s_addr = addr;
+-
+- dhd_iscan_lock();
+- DHD_ISCAN(("%s: BSS to remove %X:%X:%X:%X:%X:%X\n",
+- __func__, s_addr[0], s_addr[1], s_addr[2],
+- s_addr[3], s_addr[4], s_addr[5]));
+-
+- iscan_cur = dhd_iscan_result_buf();
+-
+- while (iscan_cur) {
+- if (iscan_cur != iscan_skip) {
+- list = (wl_iscan_results_t *)iscan_cur->iscan_buf;
+- if (!list)
+- break;
+-
+- results = (wl_scan_results_t *)&list->results;
+- if (!results)
+- break;
+-
+- if (results->version != WL_BSS_INFO_VERSION) {
+- DHD_ERROR(("%s: results->version %d != "
+- "WL_BSS_INFO_VERSION\n",
+- __func__, results->version));
+- goto done;
+- }
+-
+- bi = results->bss_info;
+- for (i = 0; i < results->count; i++) {
+- if (!bi)
+- break;
+-
+- if (!memcmp
+- (bi->BSSID.octet, addr, ETH_ALEN)) {
+- DHD_ISCAN(("%s: Del BSS[%2.2d:%2.2d] "
+- "%X:%X:%X:%X:%X:%X\n",
+- __func__, l, i, bi->BSSID.octet[0],
+- bi->BSSID.octet[1], bi->BSSID.octet[2],
+- bi->BSSID.octet[3], bi->BSSID.octet[4],
+- bi->BSSID.octet[5]));
+-
+- bi_new = bi;
+- bi = (wl_bss_info_t *)((unsigned long)
+- bi + bi->length);
+-/*
+- if(bi && bi_new) {
+- memcpy(bi_new, bi, results->buflen -
+- bi_new->length);
+- results->buflen -= bi_new->length;
+- }
+-*/
+- results->buflen -= bi_new->length;
+- results->count--;
+-
+- for (j = i; j < results->count; j++) {
+- if (bi && bi_new) {
+- DHD_ISCAN(("%s: Moved up BSS[%2.2d:%2.2d]" "%X:%X:%X:%X:%X:%X\n",
+- __func__, l, j,
+- bi->BSSID.octet[0],
+- bi->BSSID.octet[1],
+- bi->BSSID.octet[2],
+- bi->BSSID.octet[3],
+- bi->BSSID.octet[4],
+- bi->BSSID.octet[5]));
+-
+- bi_next =
+- (wl_bss_info_t *)((unsigned long)bi +
+- bi->length);
+- memcpy(bi_new, bi,
+- bi->length);
+- bi_new =
+- (wl_bss_info_t *)((unsigned long)bi_new +
+- bi_new->
+- length);
+- bi = bi_next;
+- }
+- }
+-
+- if (results->count == 0) {
+- /* Prune now empty partial
+- scan list */
+- dhd_iscan_free_buf(dhdp,
+- iscan_cur);
+- goto done;
+- }
+- break;
+- }
+- bi = (wl_bss_info_t *)((unsigned long)bi +
+- bi->length);
+- }
+- }
+- iscan_cur = iscan_cur->next;
+- l++;
+- }
+-
+-done:
+- dhd_iscan_unlock();
+- return 0;
+-}
+-
+-int dhd_iscan_remove_duplicates(void *dhdp, iscan_buf_t *iscan_cur)
+-{
+- int i = 0;
+- wl_iscan_results_t *list;
+- wl_scan_results_t *results;
+- wl_bss_info_t UNALIGNED *bi, *bi_new, *bi_next;
+-
+- dhd_iscan_lock();
+-
+- DHD_ISCAN(("%s: Scan cache before delete\n", __func__));
+- dhd_iscan_print_cache(iscan_cur);
+-
+- if (!iscan_cur)
+- goto done;
+-
+- list = (wl_iscan_results_t *)iscan_cur->iscan_buf;
+- if (!list)
+- goto done;
+-
+- results = (wl_scan_results_t *)&list->results;
+- if (!results)
+- goto done;
+-
+- if (results->version != WL_BSS_INFO_VERSION) {
+- DHD_ERROR(("%s: results->version %d != WL_BSS_INFO_VERSION\n",
+- __func__, results->version));
+- goto done;
+- }
+-
+- bi = results->bss_info;
+- for (i = 0; i < results->count; i++) {
+- if (!bi)
+- break;
+-
+- DHD_ISCAN(("%s: Find dups for BSS[%2.2d] %X:%X:%X:%X:%X:%X\n",
+- __func__, i, bi->BSSID.octet[0],
+- bi->BSSID.octet[1], bi->BSSID.octet[2],
+- bi->BSSID.octet[3], bi->BSSID.octet[4],
+- bi->BSSID.octet[5]));
+-
+- dhd_iscan_delete_bss(dhdp, bi->BSSID.octet, iscan_cur);
+-
+- bi = (wl_bss_info_t *)((unsigned long)bi + bi->length);
+- }
+-
+-done:
+- DHD_ISCAN(("%s: Scan cache after delete\n", __func__));
+- dhd_iscan_print_cache(iscan_cur);
+- dhd_iscan_unlock();
+- return 0;
+-}
+-
+-void dhd_iscan_ind_scan_confirm(void *dhdp, bool status)
+-{
+-
+- dhd_ind_scan_confirm(dhdp, status);
+-}
+-
+-int dhd_iscan_request(void *dhdp, u16 action)
+-{
+- int rc;
+- wl_iscan_params_t params;
+- dhd_pub_t *dhd = dhd_bus_pub(dhdp);
+- char buf[WLC_IOCTL_SMLEN];
+-
+- memset(¶ms, 0, sizeof(wl_iscan_params_t));
+- memcpy(¶ms.params.bssid, ðer_bcast, ETH_ALEN);
+-
+- params.params.bss_type = DOT11_BSSTYPE_ANY;
+- params.params.scan_type = DOT11_SCANTYPE_ACTIVE;
+-
+- params.params.nprobes = -1;
+- params.params.active_time = -1;
+- params.params.passive_time = -1;
+- params.params.home_time = -1;
+- params.params.channel_num = 0;
+-
+- params.version = ISCAN_REQ_VERSION;
+- params.action = action;
+- params.scan_duration = 0;
+-
+- bcm_mkiovar("iscan", (char *)¶ms, sizeof(wl_iscan_params_t), buf,
+- WLC_IOCTL_SMLEN);
+- rc = dhd_wl_ioctl(dhdp, WLC_SET_VAR, buf, WLC_IOCTL_SMLEN);
+-
+- return rc;
+-}
+-
+-static int dhd_iscan_get_partial_result(void *dhdp, uint *scan_count)
+-{
+- wl_iscan_results_t *list_buf;
+- wl_iscan_results_t list;
+- wl_scan_results_t *results;
+- iscan_buf_t *iscan_cur;
+- int status = -1;
+- dhd_pub_t *dhd = dhd_bus_pub(dhdp);
+- int rc;
+-
+- iscan_cur = dhd_iscan_allocate_buf(dhd, &iscan_chain);
+- if (!iscan_cur) {
+- DHD_ERROR(("%s: Failed to allocate node\n", __func__));
+- dhd_iscan_free_buf(dhdp, 0);
+- dhd_iscan_request(dhdp, WL_SCAN_ACTION_ABORT);
+- goto fail;
+- }
+-
+- dhd_iscan_lock();
+-
+- memset(iscan_cur->iscan_buf, 0, WLC_IW_ISCAN_MAXLEN);
+- list_buf = (wl_iscan_results_t *) iscan_cur->iscan_buf;
+- results = &list_buf->results;
+- results->buflen = WL_ISCAN_RESULTS_FIXED_SIZE;
+- results->version = 0;
+- results->count = 0;
+-
+- memset(&list, 0, sizeof(list));
+- list.results.buflen = WLC_IW_ISCAN_MAXLEN;
+- bcm_mkiovar("iscanresults", (char *)&list, WL_ISCAN_RESULTS_FIXED_SIZE,
+- iscan_cur->iscan_buf, WLC_IW_ISCAN_MAXLEN);
+- rc = dhd_wl_ioctl(dhdp, WLC_GET_VAR, iscan_cur->iscan_buf,
+- WLC_IW_ISCAN_MAXLEN);
+-
+- results->buflen = results->buflen;
+- results->version = results->version;
+- *scan_count = results->count = results->count;
+- status = list_buf->status;
+-
+- dhd_iscan_unlock();
+-
+- if (!(*scan_count))
+- dhd_iscan_free_buf(dhdp, iscan_cur);
+- else
+- dhd_iscan_remove_duplicates(dhdp, iscan_cur);
+-
+-fail:
+- return status;
+-}
+-#endif /* SIMPLE_ISCAN */
+-
+-#ifdef PNO_SUPPORT
+-int dhd_pno_clean(dhd_pub_t *dhd)
+-{
+- char iovbuf[128];
+- int pfn_enabled = 0;
+- int iov_len = 0;
+- int ret;
+-
+- /* Disable pfn */
+- iov_len =
+- bcm_mkiovar("pfn", (char *)&pfn_enabled, 4, iovbuf, sizeof(iovbuf));
+- ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+- if (ret >= 0) {
+- /* clear pfn */
+- iov_len = bcm_mkiovar("pfnclear", 0, 0, iovbuf, sizeof(iovbuf));
+- if (iov_len) {
+- ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf,
+- iov_len);
+- if (ret < 0) {
+- DHD_ERROR(("%s failed code %d\n", __func__,
+- ret));
+- }
+- } else {
+- ret = -1;
+- DHD_ERROR(("%s failed code %d\n", __func__, iov_len));
+- }
+- } else
+- DHD_ERROR(("%s failed code %d\n", __func__, ret));
+-
+- return ret;
+-}
+-
+-int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled)
+-{
+- char iovbuf[128];
+- int ret = -1;
+-
+- if ((!dhd) && ((pfn_enabled != 0) || (pfn_enabled != 1))) {
+- DHD_ERROR(("%s error exit\n", __func__));
+- return ret;
+- }
+-
+- /* Enable/disable PNO */
+- ret = bcm_mkiovar("pfn", (char *)&pfn_enabled, 4, iovbuf,
+- sizeof(iovbuf));
+- if (ret > 0) {
+- ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf,
+- sizeof(iovbuf));
+- if (ret < 0) {
+- DHD_ERROR(("%s failed for error=%d\n", __func__, ret));
+- return ret;
+- } else {
+- dhd->pno_enable = pfn_enabled;
+- DHD_TRACE(("%s set pno as %d\n", __func__,
+- dhd->pno_enable));
+- }
+- } else
+- DHD_ERROR(("%s failed err=%d\n", __func__, ret));
+-
+- return ret;
+-}
+-
+-/* Function to execute combined scan */
+-int
+-dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t *ssids_local, int nssid, unsigned char scan_fr)
+-{
+- int err = -1;
+- char iovbuf[128];
+- int k, i;
+- wl_pfn_param_t pfn_param;
+- wl_pfn_t pfn_element;
+-
+- DHD_TRACE(("%s nssid=%d nchan=%d\n", __func__, nssid, scan_fr));
+-
+- if ((!dhd) && (!ssids_local)) {
+- DHD_ERROR(("%s error exit\n", __func__));
+- err = -1;
+- }
+-
+- /* Check for broadcast ssid */
+- for (k = 0; k < nssid; k++) {
+- if (!ssids_local[k].SSID_len) {
+- DHD_ERROR(("%d: Broadcast SSID is ilegal for PNO "
+- "setting\n", k));
+- return err;
+- }
+- }
+-/* #define PNO_DUMP 1 */
+-#ifdef PNO_DUMP
+- {
+- int j;
+- for (j = 0; j < nssid; j++) {
+- DHD_ERROR(("%d: scan for %s size =%d\n", j,
+- ssids_local[j].SSID,
+- ssids_local[j].SSID_len));
+- }
+- }
+-#endif /* PNO_DUMP */
+-
+- /* clean up everything */
+- err = dhd_pno_clean(dhd);
+- if (err < 0) {
+- DHD_ERROR(("%s failed error=%d\n", __func__, err));
+- return err;
+- }
+- memset(&pfn_param, 0, sizeof(pfn_param));
+- memset(&pfn_element, 0, sizeof(pfn_element));
+-
+- /* set pfn parameters */
+- pfn_param.version = PFN_VERSION;
+- pfn_param.flags = (PFN_LIST_ORDER << SORT_CRITERIA_BIT);
+-
+- /* set up pno scan fr */
+- if (scan_fr != 0)
+- pfn_param.scan_freq = scan_fr;
+-
+- bcm_mkiovar("pfn_set", (char *)&pfn_param, sizeof(pfn_param), iovbuf,
+- sizeof(iovbuf));
+- dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+-
+- /* set all pfn ssid */
+- for (i = 0; i < nssid; i++) {
+-
+- pfn_element.bss_type = DOT11_BSSTYPE_INFRASTRUCTURE;
+- pfn_element.auth = WLAN_AUTH_OPEN;
+- pfn_element.wpa_auth = WPA_AUTH_PFN_ANY;
+- pfn_element.wsec = 0;
+- pfn_element.infra = 1;
+-
+- memcpy((char *)pfn_element.ssid.SSID, ssids_local[i].SSID,
+- ssids_local[i].SSID_len);
+- pfn_element.ssid.SSID_len = ssids_local[i].SSID_len;
+-
+- err = bcm_mkiovar("pfn_add", (char *)&pfn_element,
+- sizeof(pfn_element), iovbuf, sizeof(iovbuf));
+- if (err > 0) {
+- err = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf,
+- sizeof(iovbuf));
+- if (err < 0) {
+- DHD_ERROR(("%s failed for i=%d error=%d\n",
+- __func__, i, err));
+- return err;
+- }
+- } else
+- DHD_ERROR(("%s failed err=%d\n", __func__, err));
+- }
+-
+- /* Enable PNO */
+- /* dhd_pno_enable(dhd, 1); */
+- return err;
+-}
+-
+-int dhd_pno_get_status(dhd_pub_t *dhd)
+-{
+- int ret = -1;
+-
+- if (!dhd)
+- return ret;
+- else
+- return dhd->pno_enable;
+-}
+-
+-#endif /* PNO_SUPPORT */
+-
+-/* Androd ComboSCAN support */
+diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_custom_gpio.c b/drivers/staging/brcm80211/brcmfmac/dhd_custom_gpio.c
+deleted file mode 100644
+index 1cf6c5d..0000000
+--- a/drivers/staging/brcm80211/brcmfmac/dhd_custom_gpio.c
++++ /dev/null
+@@ -1,158 +0,0 @@
+-/*
+- * Copyright (c) 2010 Broadcom Corporation
+- *
+- * 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/netdevice.h>
+-#include <bcmutils.h>
+-
+-#include <dngl_stats.h>
+-#include <dhd.h>
+-
+-#include <wlioctl.h>
+-#include <wl_iw.h>
+-
+-#define WL_ERROR(fmt, args...) printk(fmt, ##args)
+-#define WL_TRACE(fmt, args...) no_printk(fmt, ##args)
+-
+-#ifdef CUSTOMER_HW
+-extern void bcm_wlan_power_off(int);
+-extern void bcm_wlan_power_on(int);
+-#endif /* CUSTOMER_HW */
+-#ifdef CUSTOMER_HW2
+-int wifi_set_carddetect(int on);
+-int wifi_set_power(int on, unsigned long msec);
+-int wifi_get_irq_number(unsigned long *irq_flags_ptr);
+-#endif
+-
+-#if defined(OOB_INTR_ONLY)
+-
+-#if defined(BCMLXSDMMC)
+-extern int sdioh_mmc_irq(int irq);
+-#endif /* (BCMLXSDMMC) */
+-
+-#ifdef CUSTOMER_HW3
+-#include <mach/gpio.h>
+-#endif
+-
+-/* Customer specific Host GPIO definition */
+-static int dhd_oob_gpio_num = -1; /* GG 19 */
+-
+-module_param(dhd_oob_gpio_num, int, 0644);
+-MODULE_PARM_DESC(dhd_oob_gpio_num, "DHD oob gpio number");
+-
+-int dhd_customer_oob_irq_map(unsigned long *irq_flags_ptr)
+-{
+- int host_oob_irq = 0;
+-
+-#ifdef CUSTOMER_HW2
+- host_oob_irq = wifi_get_irq_number(irq_flags_ptr);
+-
+-#else /* for NOT CUSTOMER_HW2 */
+-#if defined(CUSTOM_OOB_GPIO_NUM)
+- if (dhd_oob_gpio_num < 0)
+- dhd_oob_gpio_num = CUSTOM_OOB_GPIO_NUM;
+-#endif
+-
+- if (dhd_oob_gpio_num < 0) {
+- WL_ERROR("%s: ERROR customer specific Host GPIO is NOT defined\n",
+- __func__);
+- return dhd_oob_gpio_num;
+- }
+-
+- WL_ERROR("%s: customer specific Host GPIO number is (%d)\n",
+- __func__, dhd_oob_gpio_num);
+-
+-#if defined CUSTOMER_HW
+- host_oob_irq = MSM_GPIO_TO_INT(dhd_oob_gpio_num);
+-#elif defined CUSTOMER_HW3
+- gpio_request(dhd_oob_gpio_num, "oob irq");
+- host_oob_irq = gpio_to_irq(dhd_oob_gpio_num);
+- gpio_direction_input(dhd_oob_gpio_num);
+-#endif /* CUSTOMER_HW */
+-#endif /* CUSTOMER_HW2 */
+-
+- return host_oob_irq;
+-}
+-#endif /* defined(OOB_INTR_ONLY) */
+-
+-/* Customer function to control hw specific wlan gpios */
+-void dhd_customer_gpio_wlan_ctrl(int onoff)
+-{
+- switch (onoff) {
+- case WLAN_RESET_OFF:
+- WL_TRACE("%s: call customer specific GPIO to insert WLAN RESET\n",
+- __func__);
+-#ifdef CUSTOMER_HW
+- bcm_wlan_power_off(2);
+-#endif /* CUSTOMER_HW */
+-#ifdef CUSTOMER_HW2
+- wifi_set_power(0, 0);
+-#endif
+- WL_ERROR("=========== WLAN placed in RESET ========\n");
+- break;
+-
+- case WLAN_RESET_ON:
+- WL_TRACE("%s: callc customer specific GPIO to remove WLAN RESET\n",
+- __func__);
+-#ifdef CUSTOMER_HW
+- bcm_wlan_power_on(2);
+-#endif /* CUSTOMER_HW */
+-#ifdef CUSTOMER_HW2
+- wifi_set_power(1, 0);
+-#endif
+- WL_ERROR("=========== WLAN going back to live ========\n");
+- break;
+-
+- case WLAN_POWER_OFF:
+- WL_TRACE("%s: call customer specific GPIO to turn off WL_REG_ON\n",
+- __func__);
+-#ifdef CUSTOMER_HW
+- bcm_wlan_power_off(1);
+-#endif /* CUSTOMER_HW */
+- break;
+-
+- case WLAN_POWER_ON:
+- WL_TRACE("%s: call customer specific GPIO to turn on WL_REG_ON\n",
+- __func__);
+-#ifdef CUSTOMER_HW
+- bcm_wlan_power_on(1);
+-#endif /* CUSTOMER_HW */
+- /* Lets customer power to get stable */
+- udelay(200);
+- break;
+- }
+-}
+-
+-#ifdef GET_CUSTOM_MAC_ENABLE
+-/* Function to get custom MAC address */
+-int dhd_custom_get_mac_address(unsigned char *buf)
+-{
+- WL_TRACE("%s Enter\n", __func__);
+- if (!buf)
+- return -EINVAL;
+-
+- /* Customer access to MAC address stored outside of DHD driver */
+-
+-#ifdef EXAMPLE_GET_MAC
+- /* EXAMPLE code */
+- {
+- u8 ea_example[ETH_ALEN] = {0x00, 0x11, 0x22, 0x33, 0x44, 0xFF};
+- memcpy(buf, ea_example, ETH_ALEN);
+- }
+-#endif /* EXAMPLE_GET_MAC */
+-
+- return 0;
+-}
+-#endif /* GET_CUSTOM_MAC_ENABLE */
+diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_dbg.h b/drivers/staging/brcm80211/brcmfmac/dhd_dbg.h
+deleted file mode 100644
+index 0817f13..0000000
+--- a/drivers/staging/brcm80211/brcmfmac/dhd_dbg.h
++++ /dev/null
+@@ -1,103 +0,0 @@
+-/*
+- * Copyright (c) 2010 Broadcom Corporation
+- *
+- * 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 _dhd_dbg_
+-#define _dhd_dbg_
+-
+-#if defined(DHD_DEBUG)
+-
+-#define DHD_ERROR(args) \
+- do {if ((dhd_msg_level & DHD_ERROR_VAL) && (net_ratelimit())) \
+- printk args; } while (0)
+-#define DHD_TRACE(args) do {if (dhd_msg_level & DHD_TRACE_VAL) \
+- printk args; } while (0)
+-#define DHD_INFO(args) do {if (dhd_msg_level & DHD_INFO_VAL) \
+- printk args; } while (0)
+-#define DHD_DATA(args) do {if (dhd_msg_level & DHD_DATA_VAL) \
+- printk args; } while (0)
+-#define DHD_CTL(args) do {if (dhd_msg_level & DHD_CTL_VAL) \
+- printk args; } while (0)
+-#define DHD_TIMER(args) do {if (dhd_msg_level & DHD_TIMER_VAL) \
+- printk args; } while (0)
+-#define DHD_HDRS(args) do {if (dhd_msg_level & DHD_HDRS_VAL) \
+- printk args; } while (0)
+-#define DHD_BYTES(args) do {if (dhd_msg_level & DHD_BYTES_VAL) \
+- printk args; } while (0)
+-#define DHD_INTR(args) do {if (dhd_msg_level & DHD_INTR_VAL) \
+- printk args; } while (0)
+-#define DHD_GLOM(args) do {if (dhd_msg_level & DHD_GLOM_VAL) \
+- printk args; } while (0)
+-#define DHD_EVENT(args) do {if (dhd_msg_level & DHD_EVENT_VAL) \
+- printk args; } while (0)
+-#define DHD_BTA(args) do {if (dhd_msg_level & DHD_BTA_VAL) \
+- printk args; } while (0)
+-#define DHD_ISCAN(args) do {if (dhd_msg_level & DHD_ISCAN_VAL) \
+- printk args; } while (0)
+-
+-#define DHD_ERROR_ON() (dhd_msg_level & DHD_ERROR_VAL)
+-#define DHD_TRACE_ON() (dhd_msg_level & DHD_TRACE_VAL)
+-#define DHD_INFO_ON() (dhd_msg_level & DHD_INFO_VAL)
+-#define DHD_DATA_ON() (dhd_msg_level & DHD_DATA_VAL)
+-#define DHD_CTL_ON() (dhd_msg_level & DHD_CTL_VAL)
+-#define DHD_TIMER_ON() (dhd_msg_level & DHD_TIMER_VAL)
+-#define DHD_HDRS_ON() (dhd_msg_level & DHD_HDRS_VAL)
+-#define DHD_BYTES_ON() (dhd_msg_level & DHD_BYTES_VAL)
+-#define DHD_INTR_ON() (dhd_msg_level & DHD_INTR_VAL)
+-#define DHD_GLOM_ON() (dhd_msg_level & DHD_GLOM_VAL)
+-#define DHD_EVENT_ON() (dhd_msg_level & DHD_EVENT_VAL)
+-#define DHD_BTA_ON() (dhd_msg_level & DHD_BTA_VAL)
+-#define DHD_ISCAN_ON() (dhd_msg_level & DHD_ISCAN_VAL)
+-
+-#else /* (defined BCMDBG) || (defined DHD_DEBUG) */
+-
+-#define DHD_ERROR(args) do {if (net_ratelimit()) printk args; } while (0)
+-#define DHD_TRACE(args)
+-#define DHD_INFO(args)
+-#define DHD_DATA(args)
+-#define DHD_CTL(args)
+-#define DHD_TIMER(args)
+-#define DHD_HDRS(args)
+-#define DHD_BYTES(args)
+-#define DHD_INTR(args)
+-#define DHD_GLOM(args)
+-#define DHD_EVENT(args)
+-#define DHD_BTA(args)
+-#define DHD_ISCAN(args)
+-
+-#define DHD_ERROR_ON() 0
+-#define DHD_TRACE_ON() 0
+-#define DHD_INFO_ON() 0
+-#define DHD_DATA_ON() 0
+-#define DHD_CTL_ON() 0
+-#define DHD_TIMER_ON() 0
+-#define DHD_HDRS_ON() 0
+-#define DHD_BYTES_ON() 0
+-#define DHD_INTR_ON() 0
+-#define DHD_GLOM_ON() 0
+-#define DHD_EVENT_ON() 0
+-#define DHD_BTA_ON() 0
+-#define DHD_ISCAN_ON() 0
+-#endif /* defined(DHD_DEBUG) */
+-
+-#define DHD_LOG(args)
+-
+-#define DHD_NONE(args)
+-extern int dhd_msg_level;
+-
+-/* Defines msg bits */
+-#include <dhdioctl.h>
+-
+-#endif /* _dhd_dbg_ */
+diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_linux.c b/drivers/staging/brcm80211/brcmfmac/dhd_linux.c
+deleted file mode 100644
+index f356c56..0000000
+--- a/drivers/staging/brcm80211/brcmfmac/dhd_linux.c
++++ /dev/null
+@@ -1,2862 +0,0 @@
+-/*
+- * Copyright (c) 2010 Broadcom Corporation
+- *
+- * 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.
+- */
+-
+-#ifdef CONFIG_WIFI_CONTROL_FUNC
+-#include <linux/platform_device.h>
+-#endif
+-#include <linux/init.h>
+-#include <linux/kernel.h>
+-#include <linux/kthread.h>
+-#include <linux/slab.h>
+-#include <linux/skbuff.h>
+-#include <linux/netdevice.h>
+-#include <linux/etherdevice.h>
+-#include <linux/mmc/sdio_func.h>
+-#include <linux/random.h>
+-#include <linux/spinlock.h>
+-#include <linux/ethtool.h>
+-#include <linux/fcntl.h>
+-#include <linux/fs.h>
+-#include <linux/uaccess.h>
+-#include <bcmdefs.h>
+-#include <bcmutils.h>
+-
+-#include <dngl_stats.h>
+-#include <dhd.h>
+-#include <dhd_bus.h>
+-#include <dhd_proto.h>
+-#include <dhd_dbg.h>
+-
+-#include <wl_cfg80211.h>
+-
+-#define EPI_VERSION_STR "4.218.248.5"
+-#define ETH_P_BRCM 0x886c
+-
+-#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC)
+-#include <linux/wifi_tiwlan.h>
+-
+-struct semaphore wifi_control_sem;
+-
+-struct dhd_bus *g_bus;
+-
+-static struct wifi_platform_data *wifi_control_data;
+-static struct resource *wifi_irqres;
+-
+-int wifi_get_irq_number(unsigned long *irq_flags_ptr)
+-{
+- if (wifi_irqres) {
+- *irq_flags_ptr = wifi_irqres->flags & IRQF_TRIGGER_MASK;
+- return (int)wifi_irqres->start;
+- }
+-#ifdef CUSTOM_OOB_GPIO_NUM
+- return CUSTOM_OOB_GPIO_NUM;
+-#else
+- return -1;
+-#endif
+-}
+-
+-int wifi_set_carddetect(int on)
+-{
+- printk(KERN_ERR "%s = %d\n", __func__, on);
+- if (wifi_control_data && wifi_control_data->set_carddetect)
+- wifi_control_data->set_carddetect(on);
+- return 0;
+-}
+-
+-int wifi_set_power(int on, unsigned long msec)
+-{
+- printk(KERN_ERR "%s = %d\n", __func__, on);
+- if (wifi_control_data && wifi_control_data->set_power)
+- wifi_control_data->set_power(on);
+- if (msec)
+- mdelay(msec);
+- return 0;
+-}
+-
+-int wifi_set_reset(int on, unsigned long msec)
+-{
+- printk(KERN_ERR "%s = %d\n", __func__, on);
+- if (wifi_control_data && wifi_control_data->set_reset)
+- wifi_control_data->set_reset(on);
+- if (msec)
+- mdelay(msec);
+- return 0;
+-}
+-
+-static int wifi_probe(struct platform_device *pdev)
+-{
+- struct wifi_platform_data *wifi_ctrl =
+- (struct wifi_platform_data *)(pdev->dev.platform_data);
+-
+- printk(KERN_ERR "## %s\n", __func__);
+- wifi_irqres =
+- platform_get_resource_byname(pdev, IORESOURCE_IRQ,
+- "bcm4329_wlan_irq");
+- wifi_control_data = wifi_ctrl;
+-
+- wifi_set_power(1, 0); /* Power On */
+- wifi_set_carddetect(1); /* CardDetect (0->1) */
+-
+- up(&wifi_control_sem);
+- return 0;
+-}
+-
+-static int wifi_remove(struct platform_device *pdev)
+-{
+- struct wifi_platform_data *wifi_ctrl =
+- (struct wifi_platform_data *)(pdev->dev.platform_data);
+-
+- printk(KERN_ERR "## %s\n", __func__);
+- wifi_control_data = wifi_ctrl;
+-
+- wifi_set_carddetect(0); /* CardDetect (1->0) */
+- wifi_set_power(0, 0); /* Power Off */
+-
+- up(&wifi_control_sem);
+- return 0;
+-}
+-
+-static int wifi_suspend(struct platform_device *pdev, pm_message_t state)
+-{
+- DHD_TRACE(("##> %s\n", __func__));
+- return 0;
+-}
+-
+-static int wifi_resume(struct platform_device *pdev)
+-{
+- DHD_TRACE(("##> %s\n", __func__));
+- return 0;
+-}
+-
+-static struct platform_driver wifi_device = {
+- .probe = wifi_probe,
+- .remove = wifi_remove,
+- .suspend = wifi_suspend,
+- .resume = wifi_resume,
+- .driver = {
+- .name = KBUILD_MODNAME,
+- }
+-};
+-
+-int wifi_add_dev(void)
+-{
+- DHD_TRACE(("## Calling platform_driver_register\n"));
+- return platform_driver_register(&wifi_device);
+-}
+-
+-void wifi_del_dev(void)
+-{
+- DHD_TRACE(("## Unregister platform_driver_register\n"));
+- platform_driver_unregister(&wifi_device);
+-}
+-#endif /* defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) */
+-
+-#if defined(CONFIG_PM_SLEEP)
+-#include <linux/suspend.h>
+-atomic_t dhd_mmc_suspend;
+-DECLARE_WAIT_QUEUE_HEAD(dhd_dpc_wait);
+-#endif /* defined(CONFIG_PM_SLEEP) */
+-
+-#if defined(OOB_INTR_ONLY)
+-extern void dhd_enable_oob_intr(struct dhd_bus *bus, bool enable);
+-#endif /* defined(OOB_INTR_ONLY) */
+-
+-MODULE_AUTHOR("Broadcom Corporation");
+-MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN fullmac driver.");
+-MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN fullmac cards");
+-MODULE_LICENSE("Dual BSD/GPL");
+-
+-#define DRV_MODULE_NAME "brcmfmac"
+-
+-/* Linux wireless extension support */
+-#if defined(CONFIG_WIRELESS_EXT)
+-#include <wl_iw.h>
+-extern wl_iw_extra_params_t g_wl_iw_params;
+-#endif /* defined(CONFIG_WIRELESS_EXT) */
+-
+-#if defined(CONFIG_HAS_EARLYSUSPEND)
+-#include <linux/earlysuspend.h>
+-extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf,
+- uint len);
+-#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */
+-
+-#ifdef PKT_FILTER_SUPPORT
+-extern void dhd_pktfilter_offload_set(dhd_pub_t *dhd, char *arg);
+-extern void dhd_pktfilter_offload_enable(dhd_pub_t *dhd, char *arg, int enable,
+- int master_mode);
+-#endif
+-
+-/* Interface control information */
+-typedef struct dhd_if {
+- struct dhd_info *info; /* back pointer to dhd_info */
+- /* OS/stack specifics */
+- struct net_device *net;
+- struct net_device_stats stats;
+- int idx; /* iface idx in dongle */
+- int state; /* interface state */
+- uint subunit; /* subunit */
+- u8 mac_addr[ETH_ALEN]; /* assigned MAC address */
+- bool attached; /* Delayed attachment when unset */
+- bool txflowcontrol; /* Per interface flow control indicator */
+- char name[IFNAMSIZ]; /* linux interface name */
+-} dhd_if_t;
+-
+-/* Local private structure (extension of pub) */
+-typedef struct dhd_info {
+-#if defined(CONFIG_WIRELESS_EXT)
+- wl_iw_t iw; /* wireless extensions state (must be first) */
+-#endif /* defined(CONFIG_WIRELESS_EXT) */
+-
+- dhd_pub_t pub;
+-
+- /* OS/stack specifics */
+- dhd_if_t *iflist[DHD_MAX_IFS];
+-
+- struct semaphore proto_sem;
+- wait_queue_head_t ioctl_resp_wait;
+- struct timer_list timer;
+- bool wd_timer_valid;
+- struct tasklet_struct tasklet;
+- spinlock_t sdlock;
+- spinlock_t txqlock;
+- /* Thread based operation */
+- bool threads_only;
+- struct semaphore sdsem;
+- struct task_struct *watchdog_tsk;
+- struct semaphore watchdog_sem;
+- struct task_struct *dpc_tsk;
+- struct semaphore dpc_sem;
+-
+- /* Thread to issue ioctl for multicast */
+- struct task_struct *sysioc_tsk;
+- struct semaphore sysioc_sem;
+- bool set_multicast;
+- bool set_macaddress;
+- u8 macvalue[ETH_ALEN];
+- wait_queue_head_t ctrl_wait;
+- atomic_t pend_8021x_cnt;
+-
+-#ifdef CONFIG_HAS_EARLYSUSPEND
+- struct early_suspend early_suspend;
+-#endif /* CONFIG_HAS_EARLYSUSPEND */
+-} dhd_info_t;
+-
+-/* Definitions to provide path to the firmware and nvram
+- * example nvram_path[MOD_PARAM_PATHLEN]="/projects/wlan/nvram.txt"
+- */
+-char firmware_path[MOD_PARAM_PATHLEN];
+-char nvram_path[MOD_PARAM_PATHLEN];
+-
+-/* load firmware and/or nvram values from the filesystem */
+-module_param_string(firmware_path, firmware_path, MOD_PARAM_PATHLEN, 0);
+-module_param_string(nvram_path, nvram_path, MOD_PARAM_PATHLEN, 0);
+-
+-/* Error bits */
+-module_param(dhd_msg_level, int, 0);
+-
+-/* Spawn a thread for system ioctls (set mac, set mcast) */
+-uint dhd_sysioc = true;
+-module_param(dhd_sysioc, uint, 0);
+-
+-/* Watchdog interval */
+-uint dhd_watchdog_ms = 10;
+-module_param(dhd_watchdog_ms, uint, 0);
+-
+-#ifdef DHD_DEBUG
+-/* Console poll interval */
+-uint dhd_console_ms;
+-module_param(dhd_console_ms, uint, 0);
+-#endif /* DHD_DEBUG */
+-
+-/* ARP offload agent mode : Enable ARP Host Auto-Reply
+-and ARP Peer Auto-Reply */
+-uint dhd_arp_mode = 0xb;
+-module_param(dhd_arp_mode, uint, 0);
+-
+-/* ARP offload enable */
+-uint dhd_arp_enable = true;
+-module_param(dhd_arp_enable, uint, 0);
+-
+-/* Global Pkt filter enable control */
+-uint dhd_pkt_filter_enable = true;
+-module_param(dhd_pkt_filter_enable, uint, 0);
+-
+-/* Pkt filter init setup */
+-uint dhd_pkt_filter_init;
+-module_param(dhd_pkt_filter_init, uint, 0);
+-
+-/* Pkt filter mode control */
+-uint dhd_master_mode = true;
+-module_param(dhd_master_mode, uint, 1);
+-
+-/* Watchdog thread priority, -1 to use kernel timer */
+-int dhd_watchdog_prio = 97;
+-module_param(dhd_watchdog_prio, int, 0);
+-
+-/* DPC thread priority, -1 to use tasklet */
+-int dhd_dpc_prio = 98;
+-module_param(dhd_dpc_prio, int, 0);
+-
+-/* DPC thread priority, -1 to use tasklet */
+-extern int dhd_dongle_memsize;
+-module_param(dhd_dongle_memsize, int, 0);
+-
+-/* Contorl fw roaming */
+-#ifdef CUSTOMER_HW2
+-uint dhd_roam;
+-#else
+-uint dhd_roam = 1;
+-#endif
+-
+-/* Control radio state */
+-uint dhd_radio_up = 1;
+-
+-/* Network inteface name */
+-char iface_name[IFNAMSIZ] = "wlan";
+-module_param_string(iface_name, iface_name, IFNAMSIZ, 0);
+-
+-/* The following are specific to the SDIO dongle */
+-
+-/* IOCTL response timeout */
+-int dhd_ioctl_timeout_msec = IOCTL_RESP_TIMEOUT;
+-
+-/* Idle timeout for backplane clock */
+-int dhd_idletime = DHD_IDLETIME_TICKS;
+-module_param(dhd_idletime, int, 0);
+-
+-/* Use polling */
+-uint dhd_poll = false;
+-module_param(dhd_poll, uint, 0);
+-
+-/* Use cfg80211 */
+-uint dhd_cfg80211 = true;
+-module_param(dhd_cfg80211, uint, 0);
+-
+-/* Use interrupts */
+-uint dhd_intr = true;
+-module_param(dhd_intr, uint, 0);
+-
+-/* SDIO Drive Strength (in milliamps) */
+-uint dhd_sdiod_drive_strength = 6;
+-module_param(dhd_sdiod_drive_strength, uint, 0);
+-
+-/* Tx/Rx bounds */
+-extern uint dhd_txbound;
+-extern uint dhd_rxbound;
+-module_param(dhd_txbound, uint, 0);
+-module_param(dhd_rxbound, uint, 0);
+-
+-/* Deferred transmits */
+-extern uint dhd_deferred_tx;
+-module_param(dhd_deferred_tx, uint, 0);
+-
+-#ifdef SDTEST
+-/* Echo packet generator (pkts/s) */
+-uint dhd_pktgen;
+-module_param(dhd_pktgen, uint, 0);
+-
+-/* Echo packet len (0 => sawtooth, max 2040) */
+-uint dhd_pktgen_len;
+-module_param(dhd_pktgen_len, uint, 0);
+-#endif
+-
+-#define FAVORITE_WIFI_CP (!!dhd_cfg80211)
+-#define IS_CFG80211_FAVORITE() FAVORITE_WIFI_CP
+-#define DBG_CFG80211_GET() ((dhd_cfg80211 & WL_DBG_MASK) >> 1)
+-#define NO_FW_REQ() (dhd_cfg80211 & 0x80)
+-
+-/* Version string to report */
+-#ifdef DHD_DEBUG
+-#define DHD_COMPILED "\nCompiled in " SRCBASE
+-#else
+-#define DHD_COMPILED
+-#endif
+-
+-static void dhd_dpc(unsigned long data);
+-/* forward decl */
+-extern int dhd_wait_pend8021x(struct net_device *dev);
+-
+-#ifdef TOE
+-#ifndef BDC
+-#error TOE requires BDC
+-#endif /* !BDC */
+-static int dhd_toe_get(dhd_info_t *dhd, int idx, u32 *toe_ol);
+-static int dhd_toe_set(dhd_info_t *dhd, int idx, u32 toe_ol);
+-#endif /* TOE */
+-
+-static int dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata,
+- wl_event_msg_t *event_ptr, void **data_ptr);
+-
+-#if defined(CONFIG_PM_SLEEP)
+-static int dhd_sleep_pm_callback(struct notifier_block *nfb,
+- unsigned long action, void *ignored)
+-{
+- switch (action) {
+- case PM_HIBERNATION_PREPARE:
+- case PM_SUSPEND_PREPARE:
+- atomic_set(&dhd_mmc_suspend, true);
+- return NOTIFY_OK;
+- case PM_POST_HIBERNATION:
+- case PM_POST_SUSPEND:
+- atomic_set(&dhd_mmc_suspend, false);
+- return NOTIFY_OK;
+- }
+- return 0;
+-}
+-
+-static struct notifier_block dhd_sleep_pm_notifier = {
+- .notifier_call = dhd_sleep_pm_callback,
+- .priority = 0
+-};
+-
+-extern int register_pm_notifier(struct notifier_block *nb);
+-extern int unregister_pm_notifier(struct notifier_block *nb);
+-#endif /* defined(CONFIG_PM_SLEEP) */
+- /* && defined(DHD_GPL) */
+-static void dhd_set_packet_filter(int value, dhd_pub_t *dhd)
+-{
+-#ifdef PKT_FILTER_SUPPORT
+- DHD_TRACE(("%s: %d\n", __func__, value));
+- /* 1 - Enable packet filter, only allow unicast packet to send up */
+- /* 0 - Disable packet filter */
+- if (dhd_pkt_filter_enable) {
+- int i;
+-
+- for (i = 0; i < dhd->pktfilter_count; i++) {
+- dhd_pktfilter_offload_set(dhd, dhd->pktfilter[i]);
+- dhd_pktfilter_offload_enable(dhd, dhd->pktfilter[i],
+- value, dhd_master_mode);
+- }
+- }
+-#endif
+-}
+-
+-#if defined(CONFIG_HAS_EARLYSUSPEND)
+-static int dhd_set_suspend(int value, dhd_pub_t *dhd)
+-{
+- int power_mode = PM_MAX;
+- /* wl_pkt_filter_enable_t enable_parm; */
+- char iovbuf[32];
+- int bcn_li_dtim = 3;
+-#ifdef CUSTOMER_HW2
+- uint roamvar = 1;
+-#endif /* CUSTOMER_HW2 */
+-
+- DHD_TRACE(("%s: enter, value = %d in_suspend=%d\n",
+- __func__, value, dhd->in_suspend));
+-
+- if (dhd && dhd->up) {
+- if (value && dhd->in_suspend) {
+-
+- /* Kernel suspended */
+- DHD_TRACE(("%s: force extra Suspend setting\n",
+- __func__));
+-
+- dhdcdc_set_ioctl(dhd, 0, WLC_SET_PM,
+- (char *)&power_mode,
+- sizeof(power_mode));
+-
+- /* Enable packet filter, only allow unicast
+- packet to send up */
+- dhd_set_packet_filter(1, dhd);
+-
+- /* if dtim skip setup as default force it
+- * to wake each third dtim
+- * for better power saving.
+- * Note that side effect is chance to miss BC/MC
+- * packet
+- */
+- if ((dhd->dtim_skip == 0) || (dhd->dtim_skip == 1))
+- bcn_li_dtim = 3;
+- else
+- bcn_li_dtim = dhd->dtim_skip;
+- bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim,
+- 4, iovbuf, sizeof(iovbuf));
+- dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf,
+- sizeof(iovbuf));
+-#ifdef CUSTOMER_HW2
+- /* Disable build-in roaming to allowed \
+- * supplicant to take of romaing
+- */
+- bcm_mkiovar("roam_off", (char *)&roamvar, 4,
+- iovbuf, sizeof(iovbuf));
+- dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf,
+- sizeof(iovbuf));
+-#endif /* CUSTOMER_HW2 */
+- } else {
+-
+- /* Kernel resumed */
+- DHD_TRACE(("%s: Remove extra suspend setting\n",
+- __func__));
+-
+- power_mode = PM_FAST;
+- dhdcdc_set_ioctl(dhd, 0, WLC_SET_PM,
+- (char *)&power_mode,
+- sizeof(power_mode));
+-
+- /* disable pkt filter */
+- dhd_set_packet_filter(0, dhd);
+-
+- /* restore pre-suspend setting for dtim_skip */
+- bcm_mkiovar("bcn_li_dtim", (char *)&dhd->dtim_skip,
+- 4, iovbuf, sizeof(iovbuf));
+-
+- dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf,
+- sizeof(iovbuf));
+-#ifdef CUSTOMER_HW2
+- roamvar = 0;
+- bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf,
+- sizeof(iovbuf));
+- dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf,
+- sizeof(iovbuf));
+-#endif /* CUSTOMER_HW2 */
+- }
+- }
+-
+- return 0;
+-}
+-
+-static void dhd_suspend_resume_helper(struct dhd_info *dhd, int val)
+-{
+- dhd_pub_t *dhdp = &dhd->pub;
+-
+- dhd_os_proto_block(dhdp);
+- /* Set flag when early suspend was called */
+- dhdp->in_suspend = val;
+- if (!dhdp->suspend_disable_flag)
+- dhd_set_suspend(val, dhdp);
+- dhd_os_proto_unblock(dhdp);
+-}
+-
+-static void dhd_early_suspend(struct early_suspend *h)
+-{
+- struct dhd_info *dhd = container_of(h, struct dhd_info, early_suspend);
+-
+- DHD_TRACE(("%s: enter\n", __func__));
+-
+- if (dhd)
+- dhd_suspend_resume_helper(dhd, 1);
+-
+-}
+-
+-static void dhd_late_resume(struct early_suspend *h)
+-{
+- struct dhd_info *dhd = container_of(h, struct dhd_info, early_suspend);
+-
+- DHD_TRACE(("%s: enter\n", __func__));
+-
+- if (dhd)
+- dhd_suspend_resume_helper(dhd, 0);
+-}
+-#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */
+-
+-/*
+- * Generalized timeout mechanism. Uses spin sleep with exponential
+- * back-off until
+- * the sleep time reaches one jiffy, then switches over to task delay. Usage:
+- *
+- * dhd_timeout_start(&tmo, usec);
+- * while (!dhd_timeout_expired(&tmo))
+- * if (poll_something())
+- * break;
+- * if (dhd_timeout_expired(&tmo))
+- * fatal();
+- */
+-
+-void dhd_timeout_start(dhd_timeout_t *tmo, uint usec)
+-{
+- tmo->limit = usec;
+- tmo->increment = 0;
+- tmo->elapsed = 0;
+- tmo->tick = 1000000 / HZ;
+-}
+-
+-int dhd_timeout_expired(dhd_timeout_t *tmo)
+-{
+- /* Does nothing the first call */
+- if (tmo->increment == 0) {
+- tmo->increment = 1;
+- return 0;
+- }
+-
+- if (tmo->elapsed >= tmo->limit)
+- return 1;
+-
+- /* Add the delay that's about to take place */
+- tmo->elapsed += tmo->increment;
+-
+- if (tmo->increment < tmo->tick) {
+- udelay(tmo->increment);
+- tmo->increment *= 2;
+- if (tmo->increment > tmo->tick)
+- tmo->increment = tmo->tick;
+- } else {
+- wait_queue_head_t delay_wait;
+- DECLARE_WAITQUEUE(wait, current);
+- int pending;
+- init_waitqueue_head(&delay_wait);
+- add_wait_queue(&delay_wait, &wait);
+- set_current_state(TASK_INTERRUPTIBLE);
+- schedule_timeout(1);
+- pending = signal_pending(current);
+- remove_wait_queue(&delay_wait, &wait);
+- set_current_state(TASK_RUNNING);
+- if (pending)
+- return 1; /* Interrupted */
+- }
+-
+- return 0;
+-}
+-
+-static int dhd_net2idx(dhd_info_t *dhd, struct net_device *net)
+-{
+- int i = 0;
+-
+- ASSERT(dhd);
+- while (i < DHD_MAX_IFS) {
+- if (dhd->iflist[i] && (dhd->iflist[i]->net == net))
+- return i;
+- i++;
+- }
+-
+- return DHD_BAD_IF;
+-}
+-
+-int dhd_ifname2idx(dhd_info_t *dhd, char *name)
+-{
+- int i = DHD_MAX_IFS;
+-
+- ASSERT(dhd);
+-
+- if (name == NULL || *name == '\0')
+- return 0;
+-
+- while (--i > 0)
+- if (dhd->iflist[i]
+- && !strncmp(dhd->iflist[i]->name, name, IFNAMSIZ))
+- break;
+-
+- DHD_TRACE(("%s: return idx %d for \"%s\"\n", __func__, i, name));
+-
+- return i; /* default - the primary interface */
+-}
+-
+-char *dhd_ifname(dhd_pub_t *dhdp, int ifidx)
+-{
+- dhd_info_t *dhd = (dhd_info_t *) dhdp->info;
+-
+- ASSERT(dhd);
+-
+- if (ifidx < 0 || ifidx >= DHD_MAX_IFS) {
+- DHD_ERROR(("%s: ifidx %d out of range\n", __func__, ifidx));
+- return "<if_bad>";
+- }
+-
+- if (dhd->iflist[ifidx] == NULL) {
+- DHD_ERROR(("%s: null i/f %d\n", __func__, ifidx));
+- return "<if_null>";
+- }
+-
+- if (dhd->iflist[ifidx]->net)
+- return dhd->iflist[ifidx]->net->name;
+-
+- return "<if_none>";
+-}
+-
+-static void _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx)
+-{
+- struct net_device *dev;
+- struct netdev_hw_addr *ha;
+- u32 allmulti, cnt;
+-
+- wl_ioctl_t ioc;
+- char *buf, *bufp;
+- uint buflen;
+- int ret;
+-
+- ASSERT(dhd && dhd->iflist[ifidx]);
+- dev = dhd->iflist[ifidx]->net;
+- cnt = netdev_mc_count(dev);
+-
+- /* Determine initial value of allmulti flag */
+- allmulti = (dev->flags & IFF_ALLMULTI) ? true : false;
+-
+- /* Send down the multicast list first. */
+-
+- buflen = sizeof("mcast_list") + sizeof(cnt) + (cnt * ETH_ALEN);
+- bufp = buf = kmalloc(buflen, GFP_ATOMIC);
+- if (!bufp) {
+- DHD_ERROR(("%s: out of memory for mcast_list, cnt %d\n",
+- dhd_ifname(&dhd->pub, ifidx), cnt));
+- return;
+- }
+-
+- strcpy(bufp, "mcast_list");
+- bufp += strlen("mcast_list") + 1;
+-
+- cnt = cpu_to_le32(cnt);
+- memcpy(bufp, &cnt, sizeof(cnt));
+- bufp += sizeof(cnt);
+-
+- netdev_for_each_mc_addr(ha, dev) {
+- if (!cnt)
+- break;
+- memcpy(bufp, ha->addr, ETH_ALEN);
+- bufp += ETH_ALEN;
+- cnt--;
+- }
+-
+- memset(&ioc, 0, sizeof(ioc));
+- ioc.cmd = WLC_SET_VAR;
+- ioc.buf = buf;
+- ioc.len = buflen;
+- ioc.set = true;
+-
+- ret = dhd_prot_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len);
+- if (ret < 0) {
+- DHD_ERROR(("%s: set mcast_list failed, cnt %d\n",
+- dhd_ifname(&dhd->pub, ifidx), cnt));
+- allmulti = cnt ? true : allmulti;
+- }
+-
+- kfree(buf);
+-
+- /* Now send the allmulti setting. This is based on the setting in the
+- * net_device flags, but might be modified above to be turned on if we
+- * were trying to set some addresses and dongle rejected it...
+- */
+-
+- buflen = sizeof("allmulti") + sizeof(allmulti);
+- buf = kmalloc(buflen, GFP_ATOMIC);
+- if (!buf) {
+- DHD_ERROR(("%s: out of memory for allmulti\n",
+- dhd_ifname(&dhd->pub, ifidx)));
+- return;
+- }
+- allmulti = cpu_to_le32(allmulti);
+-
+- if (!bcm_mkiovar
+- ("allmulti", (void *)&allmulti, sizeof(allmulti), buf, buflen)) {
+- DHD_ERROR(("%s: mkiovar failed for allmulti, datalen %d "
+- "buflen %u\n", dhd_ifname(&dhd->pub, ifidx),
+- (int)sizeof(allmulti), buflen));
+- kfree(buf);
+- return;
+- }
+-
+- memset(&ioc, 0, sizeof(ioc));
+- ioc.cmd = WLC_SET_VAR;
+- ioc.buf = buf;
+- ioc.len = buflen;
+- ioc.set = true;
+-
+- ret = dhd_prot_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len);
+- if (ret < 0) {
+- DHD_ERROR(("%s: set allmulti %d failed\n",
+- dhd_ifname(&dhd->pub, ifidx),
+- le32_to_cpu(allmulti)));
+- }
+-
+- kfree(buf);
+-
+- /* Finally, pick up the PROMISC flag as well, like the NIC
+- driver does */
+-
+- allmulti = (dev->flags & IFF_PROMISC) ? true : false;
+- allmulti = cpu_to_le32(allmulti);
+-
+- memset(&ioc, 0, sizeof(ioc));
+- ioc.cmd = WLC_SET_PROMISC;
+- ioc.buf = &allmulti;
+- ioc.len = sizeof(allmulti);
+- ioc.set = true;
+-
+- ret = dhd_prot_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len);
+- if (ret < 0) {
+- DHD_ERROR(("%s: set promisc %d failed\n",
+- dhd_ifname(&dhd->pub, ifidx),
+- le32_to_cpu(allmulti)));
+- }
+-}
+-
+-static int
+-_dhd_set_mac_address(dhd_info_t *dhd, int ifidx, u8 *addr)
+-{
+- char buf[32];
+- wl_ioctl_t ioc;
+- int ret;
+-
+- DHD_TRACE(("%s enter\n", __func__));
+- if (!bcm_mkiovar
+- ("cur_etheraddr", (char *)addr, ETH_ALEN, buf, 32)) {
+- DHD_ERROR(("%s: mkiovar failed for cur_etheraddr\n",
+- dhd_ifname(&dhd->pub, ifidx)));
+- return -1;
+- }
+- memset(&ioc, 0, sizeof(ioc));
+- ioc.cmd = WLC_SET_VAR;
+- ioc.buf = buf;
+- ioc.len = 32;
+- ioc.set = true;
+-
+- ret = dhd_prot_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len);
+- if (ret < 0) {
+- DHD_ERROR(("%s: set cur_etheraddr failed\n",
+- dhd_ifname(&dhd->pub, ifidx)));
+- } else {
+- memcpy(dhd->iflist[ifidx]->net->dev_addr, addr, ETH_ALEN);
+- }
+-
+- return ret;
+-}
+-
+-#ifdef SOFTAP
+-extern struct net_device *ap_net_dev;
+-#endif
+-
+-static void dhd_op_if(dhd_if_t *ifp)
+-{
+- dhd_info_t *dhd;
+- int ret = 0, err = 0;
+-
+- ASSERT(ifp && ifp->info && ifp->idx); /* Virtual interfaces only */
+-
+- dhd = ifp->info;
+-
+- DHD_TRACE(("%s: idx %d, state %d\n", __func__, ifp->idx, ifp->state));
+-
+- switch (ifp->state) {
+- case WLC_E_IF_ADD:
+- /*
+- * Delete the existing interface before overwriting it
+- * in case we missed the WLC_E_IF_DEL event.
+- */
+- if (ifp->net != NULL) {
+- DHD_ERROR(("%s: ERROR: netdev:%s already exists, "
+- "try free & unregister\n",
+- __func__, ifp->net->name));
+- netif_stop_queue(ifp->net);
+- unregister_netdev(ifp->net);
+- free_netdev(ifp->net);
+- }
+- /* Allocate etherdev, including space for private structure */
+- ifp->net = alloc_etherdev(sizeof(dhd));
+- if (!ifp->net) {
+- DHD_ERROR(("%s: OOM - alloc_etherdev\n", __func__));
+- ret = -ENOMEM;
+- }
+- if (ret == 0) {
+- strcpy(ifp->net->name, ifp->name);
+- memcpy(netdev_priv(ifp->net), &dhd, sizeof(dhd));
+- err = dhd_net_attach(&dhd->pub, ifp->idx);
+- if (err != 0) {
+- DHD_ERROR(("%s: dhd_net_attach failed, "
+- "err %d\n",
+- __func__, err));
+- ret = -EOPNOTSUPP;
+- } else {
+-#ifdef SOFTAP
+- /* semaphore that the soft AP CODE
+- waits on */
+- extern struct semaphore ap_eth_sema;
+-
+- /* save ptr to wl0.1 netdev for use
+- in wl_iw.c */
+- ap_net_dev = ifp->net;
+- /* signal to the SOFTAP 'sleeper' thread,
+- wl0.1 is ready */
+- up(&ap_eth_sema);
+-#endif
+- DHD_TRACE(("\n ==== pid:%x, net_device for "
+- "if:%s created ===\n\n",
+- current->pid, ifp->net->name));
+- ifp->state = 0;
+- }
+- }
+- break;
+- case WLC_E_IF_DEL:
+- if (ifp->net != NULL) {
+- DHD_TRACE(("\n%s: got 'WLC_E_IF_DEL' state\n",
+- __func__));
+- netif_stop_queue(ifp->net);
+- unregister_netdev(ifp->net);
+- ret = DHD_DEL_IF; /* Make sure the free_netdev()
+- is called */
+- }
+- break;
+- default:
+- DHD_ERROR(("%s: bad op %d\n", __func__, ifp->state));
+- ASSERT(!ifp->state);
+- break;
+- }
+-
+- if (ret < 0) {
+- if (ifp->net)
+- free_netdev(ifp->net);
+-
+- dhd->iflist[ifp->idx] = NULL;
+- kfree(ifp);
+-#ifdef SOFTAP
+- if (ifp->net == ap_net_dev)
+- ap_net_dev = NULL; /* NULL SOFTAP global
+- wl0.1 as well */
+-#endif /* SOFTAP */
+- }
+-}
+-
+-static int _dhd_sysioc_thread(void *data)
+-{
+- dhd_info_t *dhd = (dhd_info_t *) data;
+- int i;
+-#ifdef SOFTAP
+- bool in_ap = false;
+-#endif
+-
+- allow_signal(SIGTERM);
+-
+- while (down_interruptible(&dhd->sysioc_sem) == 0) {
+- if (kthread_should_stop())
+- break;
+- for (i = 0; i < DHD_MAX_IFS; i++) {
+- if (dhd->iflist[i]) {
+-#ifdef SOFTAP
+- in_ap = (ap_net_dev != NULL);
+-#endif /* SOFTAP */
+- if (dhd->iflist[i]->state)
+- dhd_op_if(dhd->iflist[i]);
+-#ifdef SOFTAP
+- if (dhd->iflist[i] == NULL) {
+- DHD_TRACE(("\n\n %s: interface %d "
+- "removed!\n", __func__, i));
+- continue;
+- }
+-
+- if (in_ap && dhd->set_macaddress) {
+- DHD_TRACE(("attempt to set MAC for %s "
+- "in AP Mode," "blocked. \n",
+- dhd->iflist[i]->net->name));
+- dhd->set_macaddress = false;
+- continue;
+- }
+-
+- if (in_ap && dhd->set_multicast) {
+- DHD_TRACE(("attempt to set MULTICAST list for %s" "in AP Mode, blocked. \n",
+- dhd->iflist[i]->net->name));
+- dhd->set_multicast = false;
+- continue;
+- }
+-#endif /* SOFTAP */
+- if (dhd->set_multicast) {
+- dhd->set_multicast = false;
+- _dhd_set_multicast_list(dhd, i);
+- }
+- if (dhd->set_macaddress) {
+- dhd->set_macaddress = false;
+- _dhd_set_mac_address(dhd, i,
+- dhd->macvalue);
+- }
+- }
+- }
+- }
+- return 0;
+-}
+-
+-static int dhd_set_mac_address(struct net_device *dev, void *addr)
+-{
+- int ret = 0;
+-
+- dhd_info_t *dhd = *(dhd_info_t **) netdev_priv(dev);
+- struct sockaddr *sa = (struct sockaddr *)addr;
+- int ifidx;
+-
+- ifidx = dhd_net2idx(dhd, dev);
+- if (ifidx == DHD_BAD_IF)
+- return -1;
+-
+- ASSERT(dhd->sysioc_tsk);
+- memcpy(&dhd->macvalue, sa->sa_data, ETH_ALEN);
+- dhd->set_macaddress = true;
+- up(&dhd->sysioc_sem);
+-
+- return ret;
+-}
+-
+-static void dhd_set_multicast_list(struct net_device *dev)
+-{
+- dhd_info_t *dhd = *(dhd_info_t **) netdev_priv(dev);
+- int ifidx;
+-
+- ifidx = dhd_net2idx(dhd, dev);
+- if (ifidx == DHD_BAD_IF)
+- return;
+-
+- ASSERT(dhd->sysioc_tsk);
+- dhd->set_multicast = true;
+- up(&dhd->sysioc_sem);
+-}
+-
+-int dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, struct sk_buff *pktbuf)
+-{
+- int ret;
+- dhd_info_t *dhd = (dhd_info_t *) (dhdp->info);
+-
+- /* Reject if down */
+- if (!dhdp->up || (dhdp->busstate == DHD_BUS_DOWN))
+- return -ENODEV;
+-
+- /* Update multicast statistic */
+- if (pktbuf->len >= ETH_ALEN) {
+- u8 *pktdata = (u8 *) (pktbuf->data);
+- struct ethhdr *eh = (struct ethhdr *)pktdata;
+-
+- if (is_multicast_ether_addr(eh->h_dest))
+- dhdp->tx_multicast++;
+- if (ntohs(eh->h_proto) == ETH_P_PAE)
+- atomic_inc(&dhd->pend_8021x_cnt);
+- }
+-
+- /* If the protocol uses a data header, apply it */
+- dhd_prot_hdrpush(dhdp, ifidx, pktbuf);
+-
+- /* Use bus module to send data frame */
+-#ifdef BCMDBUS
+- ret = dbus_send_pkt(dhdp->dbus, pktbuf, NULL /* pktinfo */);
+-#else
+- ret = dhd_bus_txdata(dhdp->bus, pktbuf);
+-#endif /* BCMDBUS */
+-
+- return ret;
+-}
+-
+-static inline void *
+-osl_pkt_frmnative(struct sk_buff *skb)
+-{
+- return (void *)skb;
+-}
+-#define PKTFRMNATIVE(osh, skb) \
+- osl_pkt_frmnative((struct sk_buff *)(skb))
+-
+-static inline struct sk_buff *
+-osl_pkt_tonative(void *pkt)
+-{
+- return (struct sk_buff *)pkt;
+-}
+-#define PKTTONATIVE(osh, pkt) \
+- osl_pkt_tonative((pkt))
+-
+-static int dhd_start_xmit(struct sk_buff *skb, struct net_device *net)
+-{
+- int ret;
+- void *pktbuf;
+- dhd_info_t *dhd = *(dhd_info_t **) netdev_priv(net);
+- int ifidx;
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- /* Reject if down */
+- if (!dhd->pub.up || (dhd->pub.busstate == DHD_BUS_DOWN)) {
+- DHD_ERROR(("%s: xmit rejected pub.up=%d busstate=%d\n",
+- __func__, dhd->pub.up, dhd->pub.busstate));
+- netif_stop_queue(net);
+- return -ENODEV;
+- }
+-
+- ifidx = dhd_net2idx(dhd, net);
+- if (ifidx == DHD_BAD_IF) {
+- DHD_ERROR(("%s: bad ifidx %d\n", __func__, ifidx));
+- netif_stop_queue(net);
+- return -ENODEV;
+- }
+-
+- /* Make sure there's enough room for any header */
+- if (skb_headroom(skb) < dhd->pub.hdrlen) {
+- struct sk_buff *skb2;
+-
+- DHD_INFO(("%s: insufficient headroom\n",
+- dhd_ifname(&dhd->pub, ifidx)));
+- dhd->pub.tx_realloc++;
+- skb2 = skb_realloc_headroom(skb, dhd->pub.hdrlen);
+- dev_kfree_skb(skb);
+- skb = skb2;
+- if (skb == NULL) {
+- DHD_ERROR(("%s: skb_realloc_headroom failed\n",
+- dhd_ifname(&dhd->pub, ifidx)));
+- ret = -ENOMEM;
+- goto done;
+- }
+- }
+-
+- /* Convert to packet */
+- pktbuf = PKTFRMNATIVE(dhd->pub.osh, skb);
+- if (!pktbuf) {
+- DHD_ERROR(("%s: PKTFRMNATIVE failed\n",
+- dhd_ifname(&dhd->pub, ifidx)));
+- dev_kfree_skb_any(skb);
+- ret = -ENOMEM;
+- goto done;
+- }
+-
+- ret = dhd_sendpkt(&dhd->pub, ifidx, pktbuf);
+-
+-done:
+- if (ret)
+- dhd->pub.dstats.tx_dropped++;
+- else
+- dhd->pub.tx_packets++;
+-
+- /* Return ok: we always eat the packet */
+- return 0;
+-}
+-
+-void dhd_txflowcontrol(dhd_pub_t *dhdp, int ifidx, bool state)
+-{
+- struct net_device *net;
+- dhd_info_t *dhd = dhdp->info;
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- dhdp->txoff = state;
+- ASSERT(dhd && dhd->iflist[ifidx]);
+- net = dhd->iflist[ifidx]->net;
+- if (state == ON)
+- netif_stop_queue(net);
+- else
+- netif_wake_queue(net);
+-}
+-
+-void dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, struct sk_buff *pktbuf,
+- int numpkt)
+-{
+- dhd_info_t *dhd = (dhd_info_t *) dhdp->info;
+- struct sk_buff *skb;
+- unsigned char *eth;
+- uint len;
+- void *data;
+- struct sk_buff *pnext, *save_pktbuf;
+- int i;
+- dhd_if_t *ifp;
+- wl_event_msg_t event;
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- save_pktbuf = pktbuf;
+-
+- for (i = 0; pktbuf && i < numpkt; i++, pktbuf = pnext) {
+-
+- pnext = pktbuf->next;
+- pktbuf->next = NULL;
+-
+- skb = PKTTONATIVE(dhdp->osh, pktbuf);
+-
+- /* Get the protocol, maintain skb around eth_type_trans()
+- * The main reason for this hack is for the limitation of
+- * Linux 2.4 where 'eth_type_trans' uses the
+- * 'net->hard_header_len'
+- * to perform skb_pull inside vs ETH_HLEN. Since to avoid
+- * coping of the packet coming from the network stack to add
+- * BDC, Hardware header etc, during network interface
+- * registration
+- * we set the 'net->hard_header_len' to ETH_HLEN + extra space
+- * required
+- * for BDC, Hardware header etc. and not just the ETH_HLEN
+- */
+- eth = skb->data;
+- len = skb->len;
+-
+- ifp = dhd->iflist[ifidx];
+- if (ifp == NULL)
+- ifp = dhd->iflist[0];
+-
+- ASSERT(ifp);
+- skb->dev = ifp->net;
+- skb->protocol = eth_type_trans(skb, skb->dev);
+-
+- if (skb->pkt_type == PACKET_MULTICAST)
+- dhd->pub.rx_multicast++;
+-
+- skb->data = eth;
+- skb->len = len;
+-
+- /* Strip header, count, deliver upward */
+- skb_pull(skb, ETH_HLEN);
+-
+- /* Process special event packets and then discard them */
+- if (ntohs(skb->protocol) == ETH_P_BRCM)
+- dhd_wl_host_event(dhd, &ifidx,
+- skb_mac_header(skb),
+- &event, &data);
+-
+- ASSERT(ifidx < DHD_MAX_IFS && dhd->iflist[ifidx]);
+- if (dhd->iflist[ifidx] && !dhd->iflist[ifidx]->state)
+- ifp = dhd->iflist[ifidx];
+-
+- if (ifp->net)
+- ifp->net->last_rx = jiffies;
+-
+- dhdp->dstats.rx_bytes += skb->len;
+- dhdp->rx_packets++; /* Local count */
+-
+- if (in_interrupt()) {
+- netif_rx(skb);
+- } else {
+- /* If the receive is not processed inside an ISR,
+- * the softirqd must be woken explicitly to service
+- * the NET_RX_SOFTIRQ. In 2.6 kernels, this is handled
+- * by netif_rx_ni(), but in earlier kernels, we need
+- * to do it manually.
+- */
+- netif_rx_ni(skb);
+- }
+- }
+-}
+-
+-void dhd_event(struct dhd_info *dhd, char *evpkt, int evlen, int ifidx)
+-{
+- /* Linux version has nothing to do */
+- return;
+-}
+-
+-void dhd_txcomplete(dhd_pub_t *dhdp, struct sk_buff *txp, bool success)
+-{
+- uint ifidx;
+- dhd_info_t *dhd = (dhd_info_t *) (dhdp->info);
+- struct ethhdr *eh;
+- u16 type;
+-
+- dhd_prot_hdrpull(dhdp, &ifidx, txp);
+-
+- eh = (struct ethhdr *)(txp->data);
+- type = ntohs(eh->h_proto);
+-
+- if (type == ETH_P_PAE)
+- atomic_dec(&dhd->pend_8021x_cnt);
+-
+-}
+-
+-static struct net_device_stats *dhd_get_stats(struct net_device *net)
+-{
+- dhd_info_t *dhd = *(dhd_info_t **) netdev_priv(net);
+- dhd_if_t *ifp;
+- int ifidx;
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- ifidx = dhd_net2idx(dhd, net);
+- if (ifidx == DHD_BAD_IF)
+- return NULL;
+-
+- ifp = dhd->iflist[ifidx];
+- ASSERT(dhd && ifp);
+-
+- if (dhd->pub.up) {
+- /* Use the protocol to get dongle stats */
+- dhd_prot_dstats(&dhd->pub);
+- }
+-
+- /* Copy dongle stats to net device stats */
+- ifp->stats.rx_packets = dhd->pub.dstats.rx_packets;
+- ifp->stats.tx_packets = dhd->pub.dstats.tx_packets;
+- ifp->stats.rx_bytes = dhd->pub.dstats.rx_bytes;
+- ifp->stats.tx_bytes = dhd->pub.dstats.tx_bytes;
+- ifp->stats.rx_errors = dhd->pub.dstats.rx_errors;
+- ifp->stats.tx_errors = dhd->pub.dstats.tx_errors;
+- ifp->stats.rx_dropped = dhd->pub.dstats.rx_dropped;
+- ifp->stats.tx_dropped = dhd->pub.dstats.tx_dropped;
+- ifp->stats.multicast = dhd->pub.dstats.multicast;
+-
+- return &ifp->stats;
+-}
+-
+-static int dhd_watchdog_thread(void *data)
+-{
+- dhd_info_t *dhd = (dhd_info_t *) data;
+-
+- /* This thread doesn't need any user-level access,
+- * so get rid of all our resources
+- */
+-#ifdef DHD_SCHED
+- if (dhd_watchdog_prio > 0) {
+- struct sched_param param;
+- param.sched_priority = (dhd_watchdog_prio < MAX_RT_PRIO) ?
+- dhd_watchdog_prio : (MAX_RT_PRIO - 1);
+- setScheduler(current, SCHED_FIFO, ¶m);
+- }
+-#endif /* DHD_SCHED */
+-
+- allow_signal(SIGTERM);
+- /* Run until signal received */
+- while (1) {
+- if (kthread_should_stop())
+- break;
+- if (down_interruptible(&dhd->watchdog_sem) == 0) {
+- if (dhd->pub.dongle_reset == false) {
+- /* Call the bus module watchdog */
+- dhd_bus_watchdog(&dhd->pub);
+- }
+- /* Count the tick for reference */
+- dhd->pub.tickcnt++;
+- } else
+- break;
+- }
+- return 0;
+-}
+-
+-static void dhd_watchdog(unsigned long data)
+-{
+- dhd_info_t *dhd = (dhd_info_t *) data;
+-
+- if (dhd->watchdog_tsk) {
+- up(&dhd->watchdog_sem);
+-
+- /* Reschedule the watchdog */
+- if (dhd->wd_timer_valid) {
+- mod_timer(&dhd->timer,
+- jiffies + dhd_watchdog_ms * HZ / 1000);
+- }
+- return;
+- }
+-
+- /* Call the bus module watchdog */
+- dhd_bus_watchdog(&dhd->pub);
+-
+- /* Count the tick for reference */
+- dhd->pub.tickcnt++;
+-
+- /* Reschedule the watchdog */
+- if (dhd->wd_timer_valid)
+- mod_timer(&dhd->timer, jiffies + dhd_watchdog_ms * HZ / 1000);
+-}
+-
+-static int dhd_dpc_thread(void *data)
+-{
+- dhd_info_t *dhd = (dhd_info_t *) data;
+-
+- /* This thread doesn't need any user-level access,
+- * so get rid of all our resources
+- */
+-#ifdef DHD_SCHED
+- if (dhd_dpc_prio > 0) {
+- struct sched_param param;
+- param.sched_priority =
+- (dhd_dpc_prio <
+- MAX_RT_PRIO) ? dhd_dpc_prio : (MAX_RT_PRIO - 1);
+- setScheduler(current, SCHED_FIFO, ¶m);
+- }
+-#endif /* DHD_SCHED */
+-
+- allow_signal(SIGTERM);
+- /* Run until signal received */
+- while (1) {
+- if (kthread_should_stop())
+- break;
+- if (down_interruptible(&dhd->dpc_sem) == 0) {
+- /* Call bus dpc unless it indicated down
+- (then clean stop) */
+- if (dhd->pub.busstate != DHD_BUS_DOWN) {
+- if (dhd_bus_dpc(dhd->pub.bus)) {
+- up(&dhd->dpc_sem);
+- }
+- } else {
+- dhd_bus_stop(dhd->pub.bus, true);
+- }
+- } else
+- break;
+- }
+- return 0;
+-}
+-
+-static void dhd_dpc(unsigned long data)
+-{
+- dhd_info_t *dhd;
+-
+- dhd = (dhd_info_t *) data;
+-
+- /* Call bus dpc unless it indicated down (then clean stop) */
+- if (dhd->pub.busstate != DHD_BUS_DOWN) {
+- if (dhd_bus_dpc(dhd->pub.bus))
+- tasklet_schedule(&dhd->tasklet);
+- } else {
+- dhd_bus_stop(dhd->pub.bus, true);
+- }
+-}
+-
+-void dhd_sched_dpc(dhd_pub_t *dhdp)
+-{
+- dhd_info_t *dhd = (dhd_info_t *) dhdp->info;
+-
+- if (dhd->dpc_tsk) {
+- up(&dhd->dpc_sem);
+- return;
+- }
+-
+- tasklet_schedule(&dhd->tasklet);
+-}
+-
+-#ifdef TOE
+-/* Retrieve current toe component enables, which are kept
+- as a bitmap in toe_ol iovar */
+-static int dhd_toe_get(dhd_info_t *dhd, int ifidx, u32 *toe_ol)
+-{
+- wl_ioctl_t ioc;
+- char buf[32];
+- int ret;
+-
+- memset(&ioc, 0, sizeof(ioc));
+-
+- ioc.cmd = WLC_GET_VAR;
+- ioc.buf = buf;
+- ioc.len = (uint) sizeof(buf);
+- ioc.set = false;
+-
+- strcpy(buf, "toe_ol");
+- ret = dhd_prot_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len);
+- if (ret < 0) {
+- /* Check for older dongle image that doesn't support toe_ol */
+- if (ret == -EIO) {
+- DHD_ERROR(("%s: toe not supported by device\n",
+- dhd_ifname(&dhd->pub, ifidx)));
+- return -EOPNOTSUPP;
+- }
+-
+- DHD_INFO(("%s: could not get toe_ol: ret=%d\n",
+- dhd_ifname(&dhd->pub, ifidx), ret));
+- return ret;
+- }
+-
+- memcpy(toe_ol, buf, sizeof(u32));
+- return 0;
+-}
+-
+-/* Set current toe component enables in toe_ol iovar,
+- and set toe global enable iovar */
+-static int dhd_toe_set(dhd_info_t *dhd, int ifidx, u32 toe_ol)
+-{
+- wl_ioctl_t ioc;
+- char buf[32];
+- int toe, ret;
+-
+- memset(&ioc, 0, sizeof(ioc));
+-
+- ioc.cmd = WLC_SET_VAR;
+- ioc.buf = buf;
+- ioc.len = (uint) sizeof(buf);
+- ioc.set = true;
+-
+- /* Set toe_ol as requested */
+-
+- strcpy(buf, "toe_ol");
+- memcpy(&buf[sizeof("toe_ol")], &toe_ol, sizeof(u32));
+-
+- ret = dhd_prot_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len);
+- if (ret < 0) {
+- DHD_ERROR(("%s: could not set toe_ol: ret=%d\n",
+- dhd_ifname(&dhd->pub, ifidx), ret));
+- return ret;
+- }
+-
+- /* Enable toe globally only if any components are enabled. */
+-
+- toe = (toe_ol != 0);
+-
+- strcpy(buf, "toe");
+- memcpy(&buf[sizeof("toe")], &toe, sizeof(u32));
+-
+- ret = dhd_prot_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len);
+- if (ret < 0) {
+- DHD_ERROR(("%s: could not set toe: ret=%d\n",
+- dhd_ifname(&dhd->pub, ifidx), ret));
+- return ret;
+- }
+-
+- return 0;
+-}
+-#endif /* TOE */
+-
+-static void dhd_ethtool_get_drvinfo(struct net_device *net,
+- struct ethtool_drvinfo *info)
+-{
+- dhd_info_t *dhd = *(dhd_info_t **) netdev_priv(net);
+-
+- sprintf(info->driver, DRV_MODULE_NAME);
+- sprintf(info->version, "%lu", dhd->pub.drv_version);
+- sprintf(info->fw_version, "%s", wl_cfg80211_get_fwname());
+- sprintf(info->bus_info, "%s", dev_name(&wl_cfg80211_get_sdio_func()->dev));
+-}
+-
+-struct ethtool_ops dhd_ethtool_ops = {
+- .get_drvinfo = dhd_ethtool_get_drvinfo
+-};
+-
+-static int dhd_ethtool(dhd_info_t *dhd, void *uaddr)
+-{
+- struct ethtool_drvinfo info;
+- char drvname[sizeof(info.driver)];
+- u32 cmd;
+-#ifdef TOE
+- struct ethtool_value edata;
+- u32 toe_cmpnt, csum_dir;
+- int ret;
+-#endif
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- /* all ethtool calls start with a cmd word */
+- if (copy_from_user(&cmd, uaddr, sizeof(u32)))
+- return -EFAULT;
+-
+- switch (cmd) {
+- case ETHTOOL_GDRVINFO:
+- /* Copy out any request driver name */
+- if (copy_from_user(&info, uaddr, sizeof(info)))
+- return -EFAULT;
+- strncpy(drvname, info.driver, sizeof(info.driver));
+- drvname[sizeof(info.driver) - 1] = '\0';
+-
+- /* clear struct for return */
+- memset(&info, 0, sizeof(info));
+- info.cmd = cmd;
+-
+- /* if dhd requested, identify ourselves */
+- if (strcmp(drvname, "?dhd") == 0) {
+- sprintf(info.driver, "dhd");
+- strcpy(info.version, EPI_VERSION_STR);
+- }
+-
+- /* otherwise, require dongle to be up */
+- else if (!dhd->pub.up) {
+- DHD_ERROR(("%s: dongle is not up\n", __func__));
+- return -ENODEV;
+- }
+-
+- /* finally, report dongle driver type */
+- else if (dhd->pub.iswl)
+- sprintf(info.driver, "wl");
+- else
+- sprintf(info.driver, "xx");
+-
+- sprintf(info.version, "%lu", dhd->pub.drv_version);
+- if (copy_to_user(uaddr, &info, sizeof(info)))
+- return -EFAULT;
+- DHD_CTL(("%s: given %*s, returning %s\n", __func__,
+- (int)sizeof(drvname), drvname, info.driver));
+- break;
+-
+-#ifdef TOE
+- /* Get toe offload components from dongle */
+- case ETHTOOL_GRXCSUM:
+- case ETHTOOL_GTXCSUM:
+- ret = dhd_toe_get(dhd, 0, &toe_cmpnt);
+- if (ret < 0)
+- return ret;
+-
+- csum_dir =
+- (cmd == ETHTOOL_GTXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL;
+-
+- edata.cmd = cmd;
+- edata.data = (toe_cmpnt & csum_dir) ? 1 : 0;
+-
+- if (copy_to_user(uaddr, &edata, sizeof(edata)))
+- return -EFAULT;
+- break;
+-
+- /* Set toe offload components in dongle */
+- case ETHTOOL_SRXCSUM:
+- case ETHTOOL_STXCSUM:
+- if (copy_from_user(&edata, uaddr, sizeof(edata)))
+- return -EFAULT;
+-
+- /* Read the current settings, update and write back */
+- ret = dhd_toe_get(dhd, 0, &toe_cmpnt);
+- if (ret < 0)
+- return ret;
+-
+- csum_dir =
+- (cmd == ETHTOOL_STXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL;
+-
+- if (edata.data != 0)
+- toe_cmpnt |= csum_dir;
+- else
+- toe_cmpnt &= ~csum_dir;
+-
+- ret = dhd_toe_set(dhd, 0, toe_cmpnt);
+- if (ret < 0)
+- return ret;
+-
+- /* If setting TX checksum mode, tell Linux the new mode */
+- if (cmd == ETHTOOL_STXCSUM) {
+- if (edata.data)
+- dhd->iflist[0]->net->features |=
+- NETIF_F_IP_CSUM;
+- else
+- dhd->iflist[0]->net->features &=
+- ~NETIF_F_IP_CSUM;
+- }
+-
+- break;
+-#endif /* TOE */
+-
+- default:
+- return -EOPNOTSUPP;
+- }
+-
+- return 0;
+-}
+-
+-static int dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
+-{
+- dhd_info_t *dhd = *(dhd_info_t **) netdev_priv(net);
+- dhd_ioctl_t ioc;
+- int bcmerror = 0;
+- int buflen = 0;
+- void *buf = NULL;
+- uint driver = 0;
+- int ifidx;
+- bool is_set_key_cmd;
+-
+- ifidx = dhd_net2idx(dhd, net);
+- DHD_TRACE(("%s: ifidx %d, cmd 0x%04x\n", __func__, ifidx, cmd));
+-
+- if (ifidx == DHD_BAD_IF)
+- return -1;
+-
+-#if defined(CONFIG_WIRELESS_EXT)
+- /* linux wireless extensions */
+- if ((cmd >= SIOCIWFIRST) && (cmd <= SIOCIWLAST)) {
+- /* may recurse, do NOT lock */
+- return wl_iw_ioctl(net, ifr, cmd);
+- }
+-#endif /* defined(CONFIG_WIRELESS_EXT) */
+-
+- if (cmd == SIOCETHTOOL)
+- return dhd_ethtool(dhd, (void *)ifr->ifr_data);
+-
+- if (cmd != SIOCDEVPRIVATE)
+- return -EOPNOTSUPP;
+-
+- memset(&ioc, 0, sizeof(ioc));
+-
+- /* Copy the ioc control structure part of ioctl request */
+- if (copy_from_user(&ioc, ifr->ifr_data, sizeof(wl_ioctl_t))) {
+- bcmerror = -EINVAL;
+- goto done;
+- }
+-
+- /* Copy out any buffer passed */
+- if (ioc.buf) {
+- buflen = min_t(int, ioc.len, DHD_IOCTL_MAXLEN);
+- /* optimization for direct ioctl calls from kernel */
+- /*
+- if (segment_eq(get_fs(), KERNEL_DS)) {
+- buf = ioc.buf;
+- } else {
+- */
+- {
+- buf = kmalloc(buflen, GFP_ATOMIC);
+- if (!buf) {
+- bcmerror = -ENOMEM;
+- goto done;
+- }
+- if (copy_from_user(buf, ioc.buf, buflen)) {
+- bcmerror = -EINVAL;
+- goto done;
+- }
+- }
+- }
+-
+- /* To differentiate between wl and dhd read 4 more byes */
+- if ((copy_from_user(&driver, (char *)ifr->ifr_data + sizeof(wl_ioctl_t),
+- sizeof(uint)) != 0)) {
+- bcmerror = -EINVAL;
+- goto done;
+- }
+-
+- if (!capable(CAP_NET_ADMIN)) {
+- bcmerror = -EPERM;
+- goto done;
+- }
+-
+- /* check for local dhd ioctl and handle it */
+- if (driver == DHD_IOCTL_MAGIC) {
+- bcmerror = dhd_ioctl((void *)&dhd->pub, &ioc, buf, buflen);
+- if (bcmerror)
+- dhd->pub.bcmerror = bcmerror;
+- goto done;
+- }
+-
+- /* send to dongle (must be up, and wl) */
+- if ((dhd->pub.busstate != DHD_BUS_DATA)) {
+- DHD_ERROR(("%s DONGLE_DOWN,__func__\n", __func__));
+- bcmerror = -EIO;
+- goto done;
+- }
+-
+- if (!dhd->pub.iswl) {
+- bcmerror = -EIO;
+- goto done;
+- }
+-
+- /* Intercept WLC_SET_KEY IOCTL - serialize M4 send and set key IOCTL to
+- * prevent M4 encryption.
+- */
+- is_set_key_cmd = ((ioc.cmd == WLC_SET_KEY) ||
+- ((ioc.cmd == WLC_SET_VAR) &&
+- !(strncmp("wsec_key", ioc.buf, 9))) ||
+- ((ioc.cmd == WLC_SET_VAR) &&
+- !(strncmp("bsscfg:wsec_key", ioc.buf, 15))));
+- if (is_set_key_cmd)
+- dhd_wait_pend8021x(net);
+-
+- bcmerror =
+- dhd_prot_ioctl(&dhd->pub, ifidx, (wl_ioctl_t *)&ioc, buf, buflen);
+-
+-done:
+- if (!bcmerror && buf && ioc.buf) {
+- if (copy_to_user(ioc.buf, buf, buflen))
+- bcmerror = -EFAULT;
+- }
+-
+- kfree(buf);
+-
+- if (bcmerror > 0)
+- bcmerror = 0;
+-
+- return bcmerror;
+-}
+-
+-static int dhd_stop(struct net_device *net)
+-{
+-#if !defined(IGNORE_ETH0_DOWN)
+- dhd_info_t *dhd = *(dhd_info_t **) netdev_priv(net);
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+- if (IS_CFG80211_FAVORITE()) {
+- wl_cfg80211_down();
+- }
+- if (dhd->pub.up == 0)
+- return 0;
+-
+- /* Set state and stop OS transmissions */
+- dhd->pub.up = 0;
+- netif_stop_queue(net);
+-#else
+- DHD_ERROR(("BYPASS %s:due to BRCM compilation : under investigation\n",
+- __func__));
+-#endif /* !defined(IGNORE_ETH0_DOWN) */
+-
+- return 0;
+-}
+-
+-static int dhd_open(struct net_device *net)
+-{
+- dhd_info_t *dhd = *(dhd_info_t **) netdev_priv(net);
+-#ifdef TOE
+- u32 toe_ol;
+-#endif
+- int ifidx = dhd_net2idx(dhd, net);
+- s32 ret = 0;
+-
+- DHD_TRACE(("%s: ifidx %d\n", __func__, ifidx));
+-
+- if (ifidx == 0) { /* do it only for primary eth0 */
+-
+- /* try to bring up bus */
+- ret = dhd_bus_start(&dhd->pub);
+- if (ret != 0) {
+- DHD_ERROR(("%s: failed with code %d\n", __func__, ret));
+- return -1;
+- }
+- atomic_set(&dhd->pend_8021x_cnt, 0);
+-
+- memcpy(net->dev_addr, dhd->pub.mac, ETH_ALEN);
+-
+-#ifdef TOE
+- /* Get current TOE mode from dongle */
+- if (dhd_toe_get(dhd, ifidx, &toe_ol) >= 0
+- && (toe_ol & TOE_TX_CSUM_OL) != 0)
+- dhd->iflist[ifidx]->net->features |= NETIF_F_IP_CSUM;
+- else
+- dhd->iflist[ifidx]->net->features &= ~NETIF_F_IP_CSUM;
+-#endif
+- }
+- /* Allow transmit calls */
+- netif_start_queue(net);
+- dhd->pub.up = 1;
+- if (IS_CFG80211_FAVORITE()) {
+- if (unlikely(wl_cfg80211_up())) {
+- DHD_ERROR(("%s: failed to bring up cfg80211\n",
+- __func__));
+- return -1;
+- }
+- }
+-
+- return ret;
+-}
+-
+-int
+-dhd_add_if(dhd_info_t *dhd, int ifidx, void *handle, char *name,
+- u8 *mac_addr, u32 flags, u8 bssidx)
+-{
+- dhd_if_t *ifp;
+-
+- DHD_TRACE(("%s: idx %d, handle->%p\n", __func__, ifidx, handle));
+-
+- ASSERT(dhd && (ifidx < DHD_MAX_IFS));
+-
+- ifp = dhd->iflist[ifidx];
+- if (!ifp && !(ifp = kmalloc(sizeof(dhd_if_t), GFP_ATOMIC))) {
+- DHD_ERROR(("%s: OOM - dhd_if_t\n", __func__));
+- return -ENOMEM;
+- }
+-
+- memset(ifp, 0, sizeof(dhd_if_t));
+- ifp->info = dhd;
+- dhd->iflist[ifidx] = ifp;
+- strlcpy(ifp->name, name, IFNAMSIZ);
+- if (mac_addr != NULL)
+- memcpy(&ifp->mac_addr, mac_addr, ETH_ALEN);
+-
+- if (handle == NULL) {
+- ifp->state = WLC_E_IF_ADD;
+- ifp->idx = ifidx;
+- ASSERT(dhd->sysioc_tsk);
+- up(&dhd->sysioc_sem);
+- } else
+- ifp->net = (struct net_device *)handle;
+-
+- return 0;
+-}
+-
+-void dhd_del_if(dhd_info_t *dhd, int ifidx)
+-{
+- dhd_if_t *ifp;
+-
+- DHD_TRACE(("%s: idx %d\n", __func__, ifidx));
+-
+- ASSERT(dhd && ifidx && (ifidx < DHD_MAX_IFS));
+- ifp = dhd->iflist[ifidx];
+- if (!ifp) {
+- DHD_ERROR(("%s: Null interface\n", __func__));
+- return;
+- }
+-
+- ifp->state = WLC_E_IF_DEL;
+- ifp->idx = ifidx;
+- ASSERT(dhd->sysioc_tsk);
+- up(&dhd->sysioc_sem);
+-}
+-
+-dhd_pub_t *dhd_attach(struct dhd_bus *bus, uint bus_hdrlen)
+-{
+- dhd_info_t *dhd = NULL;
+- struct net_device *net;
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+- /* updates firmware nvram path if it was provided as module
+- paramters */
+- if ((firmware_path != NULL) && (firmware_path[0] != '\0'))
+- strcpy(fw_path, firmware_path);
+- if ((nvram_path != NULL) && (nvram_path[0] != '\0'))
+- strcpy(nv_path, nvram_path);
+-
+- /* Allocate etherdev, including space for private structure */
+- net = alloc_etherdev(sizeof(dhd));
+- if (!net) {
+- DHD_ERROR(("%s: OOM - alloc_etherdev\n", __func__));
+- goto fail;
+- }
+-
+- /* Allocate primary dhd_info */
+- dhd = kzalloc(sizeof(dhd_info_t), GFP_ATOMIC);
+- if (!dhd) {
+- DHD_ERROR(("%s: OOM - alloc dhd_info\n", __func__));
+- goto fail;
+- }
+-
+- /*
+- * Save the dhd_info into the priv
+- */
+- memcpy(netdev_priv(net), &dhd, sizeof(dhd));
+-
+- /* Set network interface name if it was provided as module parameter */
+- if (iface_name[0]) {
+- int len;
+- char ch;
+- strncpy(net->name, iface_name, IFNAMSIZ);
+- net->name[IFNAMSIZ - 1] = 0;
+- len = strlen(net->name);
+- ch = net->name[len - 1];
+- if ((ch > '9' || ch < '0') && (len < IFNAMSIZ - 2))
+- strcat(net->name, "%d");
+- }
+-
+- if (dhd_add_if(dhd, 0, (void *)net, net->name, NULL, 0, 0) ==
+- DHD_BAD_IF)
+- goto fail;
+-
+- net->netdev_ops = NULL;
+- sema_init(&dhd->proto_sem, 1);
+- /* Initialize other structure content */
+- init_waitqueue_head(&dhd->ioctl_resp_wait);
+- init_waitqueue_head(&dhd->ctrl_wait);
+-
+- /* Initialize the spinlocks */
+- spin_lock_init(&dhd->sdlock);
+- spin_lock_init(&dhd->txqlock);
+-
+- /* Link to info module */
+- dhd->pub.info = dhd;
+-
+- /* Link to bus module */
+- dhd->pub.bus = bus;
+- dhd->pub.hdrlen = bus_hdrlen;
+-
+- /* Attach and link in the protocol */
+- if (dhd_prot_attach(&dhd->pub) != 0) {
+- DHD_ERROR(("dhd_prot_attach failed\n"));
+- goto fail;
+- }
+-#if defined(CONFIG_WIRELESS_EXT)
+- /* Attach and link in the iw */
+- if (wl_iw_attach(net, (void *)&dhd->pub) != 0) {
+- DHD_ERROR(("wl_iw_attach failed\n"));
+- goto fail;
+- }
+-#endif /* defined(CONFIG_WIRELESS_EXT) */
+-
+- /* Attach and link in the cfg80211 */
+- if (IS_CFG80211_FAVORITE()) {
+- if (unlikely(wl_cfg80211_attach(net, &dhd->pub))) {
+- DHD_ERROR(("wl_cfg80211_attach failed\n"));
+- goto fail;
+- }
+- if (!NO_FW_REQ()) {
+- strcpy(fw_path, wl_cfg80211_get_fwname());
+- strcpy(nv_path, wl_cfg80211_get_nvramname());
+- }
+- }
+-
+- /* Set up the watchdog timer */
+- init_timer(&dhd->timer);
+- dhd->timer.data = (unsigned long) dhd;
+- dhd->timer.function = dhd_watchdog;
+-
+- /* Initialize thread based operation and lock */
+- sema_init(&dhd->sdsem, 1);
+- if ((dhd_watchdog_prio >= 0) && (dhd_dpc_prio >= 0))
+- dhd->threads_only = true;
+- else
+- dhd->threads_only = false;
+-
+- if (dhd_dpc_prio >= 0) {
+- /* Initialize watchdog thread */
+- sema_init(&dhd->watchdog_sem, 0);
+- dhd->watchdog_tsk = kthread_run(dhd_watchdog_thread, dhd,
+- "dhd_watchdog");
+- if (IS_ERR(dhd->watchdog_tsk)) {
+- printk(KERN_WARNING
+- "dhd_watchdog thread failed to start\n");
+- dhd->watchdog_tsk = NULL;
+- }
+- } else {
+- dhd->watchdog_tsk = NULL;
+- }
+-
+- /* Set up the bottom half handler */
+- if (dhd_dpc_prio >= 0) {
+- /* Initialize DPC thread */
+- sema_init(&dhd->dpc_sem, 0);
+- dhd->dpc_tsk = kthread_run(dhd_dpc_thread, dhd, "dhd_dpc");
+- if (IS_ERR(dhd->dpc_tsk)) {
+- printk(KERN_WARNING
+- "dhd_dpc thread failed to start\n");
+- dhd->dpc_tsk = NULL;
+- }
+- } else {
+- tasklet_init(&dhd->tasklet, dhd_dpc, (unsigned long) dhd);
+- dhd->dpc_tsk = NULL;
+- }
+-
+- if (dhd_sysioc) {
+- sema_init(&dhd->sysioc_sem, 0);
+- dhd->sysioc_tsk = kthread_run(_dhd_sysioc_thread, dhd,
+- "_dhd_sysioc");
+- if (IS_ERR(dhd->sysioc_tsk)) {
+- printk(KERN_WARNING
+- "_dhd_sysioc thread failed to start\n");
+- dhd->sysioc_tsk = NULL;
+- }
+- } else
+- dhd->sysioc_tsk = NULL;
+-
+- /*
+- * Save the dhd_info into the priv
+- */
+- memcpy(netdev_priv(net), &dhd, sizeof(dhd));
+-
+-#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC)
+- g_bus = bus;
+-#endif
+-#if defined(CONFIG_PM_SLEEP)
+- atomic_set(&dhd_mmc_suspend, false);
+- if (!IS_CFG80211_FAVORITE())
+- register_pm_notifier(&dhd_sleep_pm_notifier);
+-#endif /* defined(CONFIG_PM_SLEEP) */
+- /* && defined(DHD_GPL) */
+- /* Init lock suspend to prevent kernel going to suspend */
+-#ifdef CONFIG_HAS_EARLYSUSPEND
+- dhd->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 20;
+- dhd->early_suspend.suspend = dhd_early_suspend;
+- dhd->early_suspend.resume = dhd_late_resume;
+- register_early_suspend(&dhd->early_suspend);
+-#endif
+-
+- return &dhd->pub;
+-
+-fail:
+- if (net)
+- free_netdev(net);
+- if (dhd)
+- dhd_detach(&dhd->pub);
+-
+- return NULL;
+-}
+-
+-int dhd_bus_start(dhd_pub_t *dhdp)
+-{
+- int ret = -1;
+- dhd_info_t *dhd = (dhd_info_t *) dhdp->info;
+-#ifdef EMBEDDED_PLATFORM
+- char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" +
+- '\0' + bitvec */
+-#endif /* EMBEDDED_PLATFORM */
+-
+- ASSERT(dhd);
+-
+- DHD_TRACE(("%s:\n", __func__));
+-
+- /* try to download image and nvram to the dongle */
+- if (dhd->pub.busstate == DHD_BUS_DOWN) {
+- if (!(dhd_bus_download_firmware(dhd->pub.bus,
+- fw_path, nv_path))) {
+- DHD_ERROR(("%s: dhdsdio_probe_download failed. "
+- "firmware = %s nvram = %s\n",
+- __func__, fw_path, nv_path));
+- return -1;
+- }
+- }
+-
+- /* Start the watchdog timer */
+- dhd->pub.tickcnt = 0;
+- dhd_os_wd_timer(&dhd->pub, dhd_watchdog_ms);
+-
+- /* Bring up the bus */
+- ret = dhd_bus_init(&dhd->pub, true);
+- if (ret != 0) {
+- DHD_ERROR(("%s, dhd_bus_init failed %d\n", __func__, ret));
+- return ret;
+- }
+-#if defined(OOB_INTR_ONLY)
+- /* Host registration for OOB interrupt */
+- if (bcmsdh_register_oob_intr(dhdp)) {
+- del_timer_sync(&dhd->timer);
+- dhd->wd_timer_valid = false;
+- DHD_ERROR(("%s Host failed to resgister for OOB\n", __func__));
+- return -ENODEV;
+- }
+-
+- /* Enable oob at firmware */
+- dhd_enable_oob_intr(dhd->pub.bus, true);
+-#endif /* defined(OOB_INTR_ONLY) */
+-
+- /* If bus is not ready, can't come up */
+- if (dhd->pub.busstate != DHD_BUS_DATA) {
+- del_timer_sync(&dhd->timer);
+- dhd->wd_timer_valid = false;
+- DHD_ERROR(("%s failed bus is not ready\n", __func__));
+- return -ENODEV;
+- }
+-#ifdef EMBEDDED_PLATFORM
+- bcm_mkiovar("event_msgs", dhdp->eventmask, WL_EVENTING_MASK_LEN, iovbuf,
+- sizeof(iovbuf));
+- dhdcdc_query_ioctl(dhdp, 0, WLC_GET_VAR, iovbuf, sizeof(iovbuf));
+- memcpy(dhdp->eventmask, iovbuf, WL_EVENTING_MASK_LEN);
+-
+- setbit(dhdp->eventmask, WLC_E_SET_SSID);
+- setbit(dhdp->eventmask, WLC_E_PRUNE);
+- setbit(dhdp->eventmask, WLC_E_AUTH);
+- setbit(dhdp->eventmask, WLC_E_REASSOC);
+- setbit(dhdp->eventmask, WLC_E_REASSOC_IND);
+- setbit(dhdp->eventmask, WLC_E_DEAUTH_IND);
+- setbit(dhdp->eventmask, WLC_E_DISASSOC_IND);
+- setbit(dhdp->eventmask, WLC_E_DISASSOC);
+- setbit(dhdp->eventmask, WLC_E_JOIN);
+- setbit(dhdp->eventmask, WLC_E_ASSOC_IND);
+- setbit(dhdp->eventmask, WLC_E_PSK_SUP);
+- setbit(dhdp->eventmask, WLC_E_LINK);
+- setbit(dhdp->eventmask, WLC_E_NDIS_LINK);
+- setbit(dhdp->eventmask, WLC_E_MIC_ERROR);
+- setbit(dhdp->eventmask, WLC_E_PMKID_CACHE);
+- setbit(dhdp->eventmask, WLC_E_TXFAIL);
+- setbit(dhdp->eventmask, WLC_E_JOIN_START);
+- setbit(dhdp->eventmask, WLC_E_SCAN_COMPLETE);
+-#ifdef PNO_SUPPORT
+- setbit(dhdp->eventmask, WLC_E_PFN_NET_FOUND);
+-#endif /* PNO_SUPPORT */
+-
+-/* enable dongle roaming event */
+-
+- dhdp->pktfilter_count = 1;
+- /* Setup filter to allow only unicast */
+- dhdp->pktfilter[0] = "100 0 0 0 0x01 0x00";
+-#endif /* EMBEDDED_PLATFORM */
+-
+- /* Bus is ready, do any protocol initialization */
+- ret = dhd_prot_init(&dhd->pub);
+- if (ret < 0)
+- return ret;
+-
+- return 0;
+-}
+-
+-int
+-dhd_iovar(dhd_pub_t *pub, int ifidx, char *name, char *cmd_buf, uint cmd_len,
+- int set)
+-{
+- char buf[strlen(name) + 1 + cmd_len];
+- int len = sizeof(buf);
+- wl_ioctl_t ioc;
+- int ret;
+-
+- len = bcm_mkiovar(name, cmd_buf, cmd_len, buf, len);
+-
+- memset(&ioc, 0, sizeof(ioc));
+-
+- ioc.cmd = set ? WLC_SET_VAR : WLC_GET_VAR;
+- ioc.buf = buf;
+- ioc.len = len;
+- ioc.set = set;
+-
+- ret = dhd_prot_ioctl(pub, ifidx, &ioc, ioc.buf, ioc.len);
+- if (!set && ret >= 0)
+- memcpy(cmd_buf, buf, cmd_len);
+-
+- return ret;
+-}
+-
+-static struct net_device_ops dhd_ops_pri = {
+- .ndo_open = dhd_open,
+- .ndo_stop = dhd_stop,
+- .ndo_get_stats = dhd_get_stats,
+- .ndo_do_ioctl = dhd_ioctl_entry,
+- .ndo_start_xmit = dhd_start_xmit,
+- .ndo_set_mac_address = dhd_set_mac_address,
+- .ndo_set_multicast_list = dhd_set_multicast_list
+-};
+-
+-int dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
+-{
+- dhd_info_t *dhd = (dhd_info_t *) dhdp->info;
+- struct net_device *net;
+- u8 temp_addr[ETH_ALEN] = {
+- 0x00, 0x90, 0x4c, 0x11, 0x22, 0x33};
+-
+- DHD_TRACE(("%s: ifidx %d\n", __func__, ifidx));
+-
+- ASSERT(dhd && dhd->iflist[ifidx]);
+-
+- net = dhd->iflist[ifidx]->net;
+- ASSERT(net);
+-
+- ASSERT(!net->netdev_ops);
+- net->netdev_ops = &dhd_ops_pri;
+-
+- /*
+- * We have to use the primary MAC for virtual interfaces
+- */
+- if (ifidx != 0) {
+- /* for virtual interfaces use the primary MAC */
+- memcpy(temp_addr, dhd->pub.mac, ETH_ALEN);
+-
+- }
+-
+- if (ifidx == 1) {
+- DHD_TRACE(("%s ACCESS POINT MAC: \n", __func__));
+- /* ACCESSPOINT INTERFACE CASE */
+- temp_addr[0] |= 0X02; /* set bit 2 ,
+- - Locally Administered address */
+-
+- }
+- net->hard_header_len = ETH_HLEN + dhd->pub.hdrlen;
+- net->ethtool_ops = &dhd_ethtool_ops;
+-
+- dhd->pub.rxsz = net->mtu + net->hard_header_len + dhd->pub.hdrlen;
+-
+- memcpy(net->dev_addr, temp_addr, ETH_ALEN);
+-
+- if (register_netdev(net) != 0) {
+- DHD_ERROR(("%s: couldn't register the net device\n",
+- __func__));
+- goto fail;
+- }
+-
+- DHD_INFO(("%s: Broadcom Dongle Host Driver\n", net->name));
+-
+- return 0;
+-
+-fail:
+- net->netdev_ops = NULL;
+- return -EBADE;
+-}
+-
+-void dhd_bus_detach(dhd_pub_t *dhdp)
+-{
+- dhd_info_t *dhd;
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- if (dhdp) {
+- dhd = (dhd_info_t *) dhdp->info;
+- if (dhd) {
+- /* Stop the protocol module */
+- dhd_prot_stop(&dhd->pub);
+-
+- /* Stop the bus module */
+- dhd_bus_stop(dhd->pub.bus, true);
+-#if defined(OOB_INTR_ONLY)
+- bcmsdh_unregister_oob_intr();
+-#endif /* defined(OOB_INTR_ONLY) */
+-
+- /* Clear the watchdog timer */
+- del_timer_sync(&dhd->timer);
+- dhd->wd_timer_valid = false;
+- }
+- }
+-}
+-
+-void dhd_detach(dhd_pub_t *dhdp)
+-{
+- dhd_info_t *dhd;
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- if (dhdp) {
+- dhd = (dhd_info_t *) dhdp->info;
+- if (dhd) {
+- dhd_if_t *ifp;
+- int i;
+-
+-#if defined(CONFIG_HAS_EARLYSUSPEND)
+- if (dhd->early_suspend.suspend)
+- unregister_early_suspend(&dhd->early_suspend);
+-#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */
+-
+- for (i = 1; i < DHD_MAX_IFS; i++)
+- if (dhd->iflist[i])
+- dhd_del_if(dhd, i);
+-
+- ifp = dhd->iflist[0];
+- ASSERT(ifp);
+- if (ifp->net->netdev_ops == &dhd_ops_pri) {
+- dhd_stop(ifp->net);
+- unregister_netdev(ifp->net);
+- }
+-
+- if (dhd->watchdog_tsk) {
+- send_sig(SIGTERM, dhd->watchdog_tsk, 1);
+- kthread_stop(dhd->watchdog_tsk);
+- dhd->watchdog_tsk = NULL;
+- }
+-
+- if (dhd->dpc_tsk) {
+- send_sig(SIGTERM, dhd->dpc_tsk, 1);
+- kthread_stop(dhd->dpc_tsk);
+- dhd->dpc_tsk = NULL;
+- } else
+- tasklet_kill(&dhd->tasklet);
+-
+- if (dhd->sysioc_tsk) {
+- send_sig(SIGTERM, dhd->sysioc_tsk, 1);
+- kthread_stop(dhd->sysioc_tsk);
+- dhd->sysioc_tsk = NULL;
+- }
+-
+- dhd_bus_detach(dhdp);
+-
+- if (dhdp->prot)
+- dhd_prot_detach(dhdp);
+-
+-#if defined(CONFIG_WIRELESS_EXT)
+- wl_iw_detach();
+-#endif /* (CONFIG_WIRELESS_EXT) */
+-
+- if (IS_CFG80211_FAVORITE())
+- wl_cfg80211_detach();
+-
+-#if defined(CONFIG_PM_SLEEP)
+- if (!IS_CFG80211_FAVORITE())
+- unregister_pm_notifier(&dhd_sleep_pm_notifier);
+-#endif /* defined(CONFIG_PM_SLEEP) */
+- /* && defined(DHD_GPL) */
+- free_netdev(ifp->net);
+- kfree(ifp);
+- kfree(dhd);
+- }
+- }
+-}
+-
+-static void __exit dhd_module_cleanup(void)
+-{
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- dhd_bus_unregister();
+-#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC)
+- wifi_del_dev();
+-#endif
+- /* Call customer gpio to turn off power with WL_REG_ON signal */
+- dhd_customer_gpio_wlan_ctrl(WLAN_POWER_OFF);
+-}
+-
+-static int __init dhd_module_init(void)
+-{
+- int error;
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- /* Sanity check on the module parameters */
+- do {
+- /* Both watchdog and DPC as tasklets are ok */
+- if ((dhd_watchdog_prio < 0) && (dhd_dpc_prio < 0))
+- break;
+-
+- /* If both watchdog and DPC are threads, TX must be deferred */
+- if ((dhd_watchdog_prio >= 0) && (dhd_dpc_prio >= 0)
+- && dhd_deferred_tx)
+- break;
+-
+- DHD_ERROR(("Invalid module parameters.\n"));
+- return -EINVAL;
+- } while (0);
+- /* Call customer gpio to turn on power with WL_REG_ON signal */
+- dhd_customer_gpio_wlan_ctrl(WLAN_POWER_ON);
+-
+-#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC)
+- sema_init(&wifi_control_sem, 0);
+-
+- error = wifi_add_dev();
+- if (error) {
+- DHD_ERROR(("%s: platform_driver_register failed\n", __func__));
+- goto failed;
+- }
+-
+- /* Waiting callback after platform_driver_register is done or
+- exit with error */
+- if (down_timeout(&wifi_control_sem, msecs_to_jiffies(1000)) != 0) {
+- printk(KERN_ERR "%s: platform_driver_register timeout\n",
+- __func__);
+- /* remove device */
+- wifi_del_dev();
+- goto failed;
+- }
+-#endif /* #if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) */
+-
+- error = dhd_bus_register();
+-
+- if (error) {
+- DHD_ERROR(("%s: sdio_register_driver failed\n", __func__));
+- goto failed;
+- }
+- return error;
+-
+-failed:
+- /* turn off power and exit */
+- dhd_customer_gpio_wlan_ctrl(WLAN_POWER_OFF);
+- return -EINVAL;
+-}
+-
+-module_init(dhd_module_init);
+-module_exit(dhd_module_cleanup);
+-
+-/*
+- * OS specific functions required to implement DHD driver in OS independent way
+- */
+-int dhd_os_proto_block(dhd_pub_t *pub)
+-{
+- dhd_info_t *dhd = (dhd_info_t *) (pub->info);
+-
+- if (dhd) {
+- down(&dhd->proto_sem);
+- return 1;
+- }
+- return 0;
+-}
+-
+-int dhd_os_proto_unblock(dhd_pub_t *pub)
+-{
+- dhd_info_t *dhd = (dhd_info_t *) (pub->info);
+-
+- if (dhd) {
+- up(&dhd->proto_sem);
+- return 1;
+- }
+-
+- return 0;
+-}
+-
+-unsigned int dhd_os_get_ioctl_resp_timeout(void)
+-{
+- return (unsigned int)dhd_ioctl_timeout_msec;
+-}
+-
+-void dhd_os_set_ioctl_resp_timeout(unsigned int timeout_msec)
+-{
+- dhd_ioctl_timeout_msec = (int)timeout_msec;
+-}
+-
+-int dhd_os_ioctl_resp_wait(dhd_pub_t *pub, uint *condition, bool *pending)
+-{
+- dhd_info_t *dhd = (dhd_info_t *) (pub->info);
+- DECLARE_WAITQUEUE(wait, current);
+- int timeout = dhd_ioctl_timeout_msec;
+-
+- /* Convert timeout in millsecond to jiffies */
+- timeout = timeout * HZ / 1000;
+-
+- /* Wait until control frame is available */
+- add_wait_queue(&dhd->ioctl_resp_wait, &wait);
+- set_current_state(TASK_INTERRUPTIBLE);
+-
+- while (!(*condition) && (!signal_pending(current) && timeout))
+- timeout = schedule_timeout(timeout);
+-
+- if (signal_pending(current))
+- *pending = true;
+-
+- set_current_state(TASK_RUNNING);
+- remove_wait_queue(&dhd->ioctl_resp_wait, &wait);
+-
+- return timeout;
+-}
+-
+-int dhd_os_ioctl_resp_wake(dhd_pub_t *pub)
+-{
+- dhd_info_t *dhd = (dhd_info_t *) (pub->info);
+-
+- if (waitqueue_active(&dhd->ioctl_resp_wait))
+- wake_up_interruptible(&dhd->ioctl_resp_wait);
+-
+- return 0;
+-}
+-
+-void dhd_os_wd_timer(void *bus, uint wdtick)
+-{
+- dhd_pub_t *pub = bus;
+- static uint save_dhd_watchdog_ms;
+- dhd_info_t *dhd = (dhd_info_t *) pub->info;
+-
+- /* don't start the wd until fw is loaded */
+- if (pub->busstate == DHD_BUS_DOWN)
+- return;
+-
+- /* Totally stop the timer */
+- if (!wdtick && dhd->wd_timer_valid == true) {
+- del_timer_sync(&dhd->timer);
+- dhd->wd_timer_valid = false;
+- save_dhd_watchdog_ms = wdtick;
+- return;
+- }
+-
+- if (wdtick) {
+- dhd_watchdog_ms = (uint) wdtick;
+-
+- if (save_dhd_watchdog_ms != dhd_watchdog_ms) {
+-
+- if (dhd->wd_timer_valid == true)
+- /* Stop timer and restart at new value */
+- del_timer_sync(&dhd->timer);
+-
+- /* Create timer again when watchdog period is
+- dynamically changed or in the first instance
+- */
+- dhd->timer.expires =
+- jiffies + dhd_watchdog_ms * HZ / 1000;
+- add_timer(&dhd->timer);
+-
+- } else {
+- /* Re arm the timer, at last watchdog period */
+- mod_timer(&dhd->timer,
+- jiffies + dhd_watchdog_ms * HZ / 1000);
+- }
+-
+- dhd->wd_timer_valid = true;
+- save_dhd_watchdog_ms = wdtick;
+- }
+-}
+-
+-void *dhd_os_open_image(char *filename)
+-{
+- struct file *fp;
+-
+- if (IS_CFG80211_FAVORITE() && !NO_FW_REQ())
+- return wl_cfg80211_request_fw(filename);
+-
+- fp = filp_open(filename, O_RDONLY, 0);
+- /*
+- * 2.6.11 (FC4) supports filp_open() but later revs don't?
+- * Alternative:
+- * fp = open_namei(AT_FDCWD, filename, O_RD, 0);
+- * ???
+- */
+- if (IS_ERR(fp))
+- fp = NULL;
+-
+- return fp;
+-}
+-
+-int dhd_os_get_image_block(char *buf, int len, void *image)
+-{
+- struct file *fp = (struct file *)image;
+- int rdlen;
+-
+- if (IS_CFG80211_FAVORITE() && !NO_FW_REQ())
+- return wl_cfg80211_read_fw(buf, len);
+-
+- if (!image)
+- return 0;
+-
+- rdlen = kernel_read(fp, fp->f_pos, buf, len);
+- if (rdlen > 0)
+- fp->f_pos += rdlen;
+-
+- return rdlen;
+-}
+-
+-void dhd_os_close_image(void *image)
+-{
+- if (IS_CFG80211_FAVORITE() && !NO_FW_REQ())
+- return wl_cfg80211_release_fw();
+- if (image)
+- filp_close((struct file *)image, NULL);
+-}
+-
+-void dhd_os_sdlock(dhd_pub_t *pub)
+-{
+- dhd_info_t *dhd;
+-
+- dhd = (dhd_info_t *) (pub->info);
+-
+- if (dhd->threads_only)
+- down(&dhd->sdsem);
+- else
+- spin_lock_bh(&dhd->sdlock);
+-}
+-
+-void dhd_os_sdunlock(dhd_pub_t *pub)
+-{
+- dhd_info_t *dhd;
+-
+- dhd = (dhd_info_t *) (pub->info);
+-
+- if (dhd->threads_only)
+- up(&dhd->sdsem);
+- else
+- spin_unlock_bh(&dhd->sdlock);
+-}
+-
+-void dhd_os_sdlock_txq(dhd_pub_t *pub)
+-{
+- dhd_info_t *dhd;
+-
+- dhd = (dhd_info_t *) (pub->info);
+- spin_lock_bh(&dhd->txqlock);
+-}
+-
+-void dhd_os_sdunlock_txq(dhd_pub_t *pub)
+-{
+- dhd_info_t *dhd;
+-
+- dhd = (dhd_info_t *) (pub->info);
+- spin_unlock_bh(&dhd->txqlock);
+-}
+-
+-void dhd_os_sdlock_rxq(dhd_pub_t *pub)
+-{
+-}
+-
+-void dhd_os_sdunlock_rxq(dhd_pub_t *pub)
+-{
+-}
+-
+-void dhd_os_sdtxlock(dhd_pub_t *pub)
+-{
+- dhd_os_sdlock(pub);
+-}
+-
+-void dhd_os_sdtxunlock(dhd_pub_t *pub)
+-{
+- dhd_os_sdunlock(pub);
+-}
+-
+-static int
+-dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata,
+- wl_event_msg_t *event, void **data)
+-{
+- int bcmerror = 0;
+-
+- ASSERT(dhd != NULL);
+-
+- bcmerror = wl_host_event(dhd, ifidx, pktdata, event, data);
+- if (bcmerror != 0)
+- return bcmerror;
+-
+-#if defined(CONFIG_WIRELESS_EXT)
+- if (!IS_CFG80211_FAVORITE()) {
+- if ((dhd->iflist[*ifidx] == NULL)
+- || (dhd->iflist[*ifidx]->net == NULL)) {
+- DHD_ERROR(("%s Exit null pointer\n", __func__));
+- return bcmerror;
+- }
+-
+- if (dhd->iflist[*ifidx]->net)
+- wl_iw_event(dhd->iflist[*ifidx]->net, event, *data);
+- }
+-#endif /* defined(CONFIG_WIRELESS_EXT) */
+-
+- if (IS_CFG80211_FAVORITE()) {
+- ASSERT(dhd->iflist[*ifidx] != NULL);
+- ASSERT(dhd->iflist[*ifidx]->net != NULL);
+- if (dhd->iflist[*ifidx]->net)
+- wl_cfg80211_event(dhd->iflist[*ifidx]->net, event,
+- *data);
+- }
+-
+- return bcmerror;
+-}
+-
+-/* send up locally generated event */
+-void dhd_sendup_event(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data)
+-{
+- switch (be32_to_cpu(event->event_type)) {
+- default:
+- break;
+- }
+-}
+-
+-void dhd_wait_for_event(dhd_pub_t *dhd, bool *lockvar)
+-{
+- struct dhd_info *dhdinfo = dhd->info;
+- dhd_os_sdunlock(dhd);
+- wait_event_interruptible_timeout(dhdinfo->ctrl_wait,
+- (*lockvar == false), HZ * 2);
+- dhd_os_sdlock(dhd);
+- return;
+-}
+-
+-void dhd_wait_event_wakeup(dhd_pub_t *dhd)
+-{
+- struct dhd_info *dhdinfo = dhd->info;
+- if (waitqueue_active(&dhdinfo->ctrl_wait))
+- wake_up_interruptible(&dhdinfo->ctrl_wait);
+- return;
+-}
+-
+-int dhd_dev_reset(struct net_device *dev, u8 flag)
+-{
+- dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+-
+- /* Turning off watchdog */
+- if (flag)
+- dhd_os_wd_timer(&dhd->pub, 0);
+-
+- dhd_bus_devreset(&dhd->pub, flag);
+-
+- /* Turning on watchdog back */
+- if (!flag)
+- dhd_os_wd_timer(&dhd->pub, dhd_watchdog_ms);
+- DHD_ERROR(("%s: WLAN OFF DONE\n", __func__));
+-
+- return 1;
+-}
+-
+-int net_os_set_suspend_disable(struct net_device *dev, int val)
+-{
+- dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+- int ret = 0;
+-
+- if (dhd) {
+- ret = dhd->pub.suspend_disable_flag;
+- dhd->pub.suspend_disable_flag = val;
+- }
+- return ret;
+-}
+-
+-int net_os_set_suspend(struct net_device *dev, int val)
+-{
+- int ret = 0;
+-#if defined(CONFIG_HAS_EARLYSUSPEND)
+- dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+-
+- if (dhd) {
+- dhd_os_proto_block(&dhd->pub);
+- ret = dhd_set_suspend(val, &dhd->pub);
+- dhd_os_proto_unblock(&dhd->pub);
+- }
+-#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */
+- return ret;
+-}
+-
+-int net_os_set_dtim_skip(struct net_device *dev, int val)
+-{
+- dhd_info_t *dhd = *(dhd_info_t **) netdev_priv(dev);
+-
+- if (dhd)
+- dhd->pub.dtim_skip = val;
+-
+- return 0;
+-}
+-
+-int net_os_set_packet_filter(struct net_device *dev, int val)
+-{
+- dhd_info_t *dhd = *(dhd_info_t **) netdev_priv(dev);
+- int ret = 0;
+-
+- /* Packet filtering is set only if we still in early-suspend and
+- * we need either to turn it ON or turn it OFF
+- * We can always turn it OFF in case of early-suspend, but we turn it
+- * back ON only if suspend_disable_flag was not set
+- */
+- if (dhd && dhd->pub.up) {
+- dhd_os_proto_block(&dhd->pub);
+- if (dhd->pub.in_suspend) {
+- if (!val || (val && !dhd->pub.suspend_disable_flag))
+- dhd_set_packet_filter(val, &dhd->pub);
+- }
+- dhd_os_proto_unblock(&dhd->pub);
+- }
+- return ret;
+-}
+-
+-void dhd_dev_init_ioctl(struct net_device *dev)
+-{
+- dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+-
+- dhd_preinit_ioctls(&dhd->pub);
+-}
+-
+-#ifdef PNO_SUPPORT
+-/* Linux wrapper to call common dhd_pno_clean */
+-int dhd_dev_pno_reset(struct net_device *dev)
+-{
+- dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+-
+- return dhd_pno_clean(&dhd->pub);
+-}
+-
+-/* Linux wrapper to call common dhd_pno_enable */
+-int dhd_dev_pno_enable(struct net_device *dev, int pfn_enabled)
+-{
+- dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+-
+- return dhd_pno_enable(&dhd->pub, pfn_enabled);
+-}
+-
+-/* Linux wrapper to call common dhd_pno_set */
+-int
+-dhd_dev_pno_set(struct net_device *dev, wlc_ssid_t *ssids_local, int nssid,
+- unsigned char scan_fr)
+-{
+- dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+-
+- return dhd_pno_set(&dhd->pub, ssids_local, nssid, scan_fr);
+-}
+-
+-/* Linux wrapper to get pno status */
+-int dhd_dev_get_pno_status(struct net_device *dev)
+-{
+- dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+-
+- return dhd_pno_get_status(&dhd->pub);
+-}
+-
+-#endif /* PNO_SUPPORT */
+-
+-static int dhd_get_pend_8021x_cnt(dhd_info_t *dhd)
+-{
+- return atomic_read(&dhd->pend_8021x_cnt);
+-}
+-
+-#define MAX_WAIT_FOR_8021X_TX 10
+-
+-int dhd_wait_pend8021x(struct net_device *dev)
+-{
+- dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+- int timeout = 10 * HZ / 1000;
+- int ntimes = MAX_WAIT_FOR_8021X_TX;
+- int pend = dhd_get_pend_8021x_cnt(dhd);
+-
+- while (ntimes && pend) {
+- if (pend) {
+- set_current_state(TASK_INTERRUPTIBLE);
+- schedule_timeout(timeout);
+- set_current_state(TASK_RUNNING);
+- ntimes--;
+- }
+- pend = dhd_get_pend_8021x_cnt(dhd);
+- }
+- return pend;
+-}
+-
+-void wl_os_wd_timer(struct net_device *ndev, uint wdtick)
+-{
+- dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(ndev);
+-
+- dhd_os_wd_timer(&dhd->pub, wdtick);
+-}
+-
+-#ifdef DHD_DEBUG
+-int write_to_file(dhd_pub_t *dhd, u8 *buf, int size)
+-{
+- int ret = 0;
+- struct file *fp;
+- mm_segment_t old_fs;
+- loff_t pos = 0;
+-
+- /* change to KERNEL_DS address limit */
+- old_fs = get_fs();
+- set_fs(KERNEL_DS);
+-
+- /* open file to write */
+- fp = filp_open("/tmp/mem_dump", O_WRONLY | O_CREAT, 0640);
+- if (!fp) {
+- DHD_ERROR(("%s: open file error\n", __func__));
+- ret = -1;
+- goto exit;
+- }
+-
+- /* Write buf to file */
+- fp->f_op->write(fp, buf, size, &pos);
+-
+-exit:
+- /* free buf before return */
+- kfree(buf);
+- /* close file before return */
+- if (fp)
+- filp_close(fp, current->files);
+- /* restore previous address limit */
+- set_fs(old_fs);
+-
+- return ret;
+-}
+-#endif /* DHD_DEBUG */
+diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_linux_sched.c b/drivers/staging/brcm80211/brcmfmac/dhd_linux_sched.c
+deleted file mode 100644
+index c66f1c2..0000000
+--- a/drivers/staging/brcm80211/brcmfmac/dhd_linux_sched.c
++++ /dev/null
+@@ -1,25 +0,0 @@
+-/*
+- * Copyright (c) 2010 Broadcom Corporation
+- *
+- * 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/kernel.h>
+-#include <linux/module.h>
+-#include <linux/sched.h>
+-
+-int setScheduler(struct task_struct *p, int policy, struct sched_param *param)
+-{
+- int rc = 0;
+- rc = sched_setscheduler(p, policy, param);
+- return rc;
+-}
+diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_proto.h b/drivers/staging/brcm80211/brcmfmac/dhd_proto.h
+deleted file mode 100644
+index 030d5ff..0000000
+--- a/drivers/staging/brcm80211/brcmfmac/dhd_proto.h
++++ /dev/null
+@@ -1,90 +0,0 @@
+-/*
+- * Copyright (c) 2010 Broadcom Corporation
+- *
+- * 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 _dhd_proto_h_
+-#define _dhd_proto_h_
+-
+-#include <dhdioctl.h>
+-#include <wlioctl.h>
+-
+-#ifndef IOCTL_RESP_TIMEOUT
+-#define IOCTL_RESP_TIMEOUT 2000 /* In milli second */
+-#endif
+-
+-#ifndef IOCTL_CHIP_ACTIVE_TIMEOUT
+-#define IOCTL_CHIP_ACTIVE_TIMEOUT 10 /* In milli second */
+-#endif
+-
+-/*
+- * Exported from the dhd protocol module (dhd_cdc, dhd_rndis)
+- */
+-
+-/* Linkage, sets prot link and updates hdrlen in pub */
+-extern int dhd_prot_attach(dhd_pub_t *dhdp);
+-
+-/* Unlink, frees allocated protocol memory (including dhd_prot) */
+-extern void dhd_prot_detach(dhd_pub_t *dhdp);
+-
+-/* Initialize protocol: sync w/dongle state.
+- * Sets dongle media info (iswl, drv_version, mac address).
+- */
+-extern int dhd_prot_init(dhd_pub_t *dhdp);
+-
+-/* Stop protocol: sync w/dongle state. */
+-extern void dhd_prot_stop(dhd_pub_t *dhdp);
+-
+-/* Add any protocol-specific data header.
+- * Caller must reserve prot_hdrlen prepend space.
+- */
+-extern void dhd_prot_hdrpush(dhd_pub_t *, int ifidx, struct sk_buff *txp);
+-
+-/* Remove any protocol-specific data header. */
+-extern int dhd_prot_hdrpull(dhd_pub_t *, int *ifidx, struct sk_buff *rxp);
+-
+-/* Use protocol to issue ioctl to dongle */
+-extern int dhd_prot_ioctl(dhd_pub_t *dhd, int ifidx, wl_ioctl_t *ioc,
+- void *buf, int len);
+-
+-/* Check for and handle local prot-specific iovar commands */
+-extern int dhd_prot_iovar_op(dhd_pub_t *dhdp, const char *name,
+- void *params, int plen, void *arg, int len,
+- bool set);
+-
+-/* Add prot dump output to a buffer */
+-extern void dhd_prot_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf);
+-
+-/* Update local copy of dongle statistics */
+-extern void dhd_prot_dstats(dhd_pub_t *dhdp);
+-
+-extern int dhd_ioctl(dhd_pub_t *dhd_pub, dhd_ioctl_t *ioc, void *buf,
+- uint buflen);
+-
+-extern int dhd_preinit_ioctls(dhd_pub_t *dhd);
+-
+-/********************************
+- * For version-string expansion *
+- */
+-#if defined(BDC)
+-#define DHD_PROTOCOL "bdc"
+-#elif defined(CDC)
+-#define DHD_PROTOCOL "cdc"
+-#elif defined(RNDIS)
+-#define DHD_PROTOCOL "rndis"
+-#else
+-#define DHD_PROTOCOL "unknown"
+-#endif /* proto */
+-
+-#endif /* _dhd_proto_h_ */
+diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c b/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c
+deleted file mode 100644
+index a71c6f8..0000000
+--- a/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c
++++ /dev/null
+@@ -1,6390 +0,0 @@
+-/*
+- * Copyright (c) 2010 Broadcom Corporation
+- *
+- * 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/types.h>
+-#include <linux/kernel.h>
+-#include <linux/printk.h>
+-#include <linux/pci_ids.h>
+-#include <linux/netdevice.h>
+-#include <bcmdefs.h>
+-#include <bcmsdh.h>
+-
+-#ifdef BCMEMBEDIMAGE
+-#include BCMEMBEDIMAGE
+-#endif /* BCMEMBEDIMAGE */
+-
+-#include <bcmdefs.h>
+-#include <bcmutils.h>
+-#include <bcmdevs.h>
+-
+-#include <hndsoc.h>
+-#ifdef DHD_DEBUG
+-#include <hndrte_armtrap.h>
+-#include <hndrte_cons.h>
+-#endif /* DHD_DEBUG */
+-#include <sbchipc.h>
+-#include <sbhnddma.h>
+-
+-#include <sdio.h>
+-#include <sbsdio.h>
+-#include <sbsdpcmdev.h>
+-#include <bcmsdpcm.h>
+-
+-#include <proto/802.11.h>
+-
+-#include <dngl_stats.h>
+-#include <dhd.h>
+-#include <dhd_bus.h>
+-#include <dhd_proto.h>
+-#include <dhd_dbg.h>
+-#include <dhdioctl.h>
+-#include <sdiovar.h>
+-#include <bcmchip.h>
+-
+-#ifndef DHDSDIO_MEM_DUMP_FNAME
+-#define DHDSDIO_MEM_DUMP_FNAME "mem_dump"
+-#endif
+-
+-#define TXQLEN 2048 /* bulk tx queue length */
+-#define TXHI (TXQLEN - 256) /* turn on flow control above TXHI */
+-#define TXLOW (TXHI - 256) /* turn off flow control below TXLOW */
+-#define PRIOMASK 7
+-
+-#define TXRETRIES 2 /* # of retries for tx frames */
+-
+-#if defined(CONFIG_MACH_SANDGATE2G)
+-#define DHD_RXBOUND 250 /* Default for max rx frames in
+- one scheduling */
+-#else
+-#define DHD_RXBOUND 50 /* Default for max rx frames in
+- one scheduling */
+-#endif /* defined(CONFIG_MACH_SANDGATE2G) */
+-
+-#define DHD_TXBOUND 20 /* Default for max tx frames in
+- one scheduling */
+-
+-#define DHD_TXMINMAX 1 /* Max tx frames if rx still pending */
+-
+-#define MEMBLOCK 2048 /* Block size used for downloading
+- of dongle image */
+-#define MAX_DATA_BUF (32 * 1024) /* Must be large enough to hold
+- biggest possible glom */
+-
+-/* Packet alignment for most efficient SDIO (can change based on platform) */
+-#ifndef DHD_SDALIGN
+-#define DHD_SDALIGN 32
+-#endif
+-#if !ISPOWEROF2(DHD_SDALIGN)
+-#error DHD_SDALIGN is not a power of 2!
+-#endif
+-
+-#ifndef DHD_FIRSTREAD
+-#define DHD_FIRSTREAD 32
+-#endif
+-#if !ISPOWEROF2(DHD_FIRSTREAD)
+-#error DHD_FIRSTREAD is not a power of 2!
+-#endif
+-
+-/* Total length of frame header for dongle protocol */
+-#define SDPCM_HDRLEN (SDPCM_FRAMETAG_LEN + SDPCM_SWHEADER_LEN)
+-#ifdef SDTEST
+-#define SDPCM_RESERVE (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN)
+-#else
+-#define SDPCM_RESERVE (SDPCM_HDRLEN + DHD_SDALIGN)
+-#endif
+-
+-/* Space for header read, limit for data packets */
+-#ifndef MAX_HDR_READ
+-#define MAX_HDR_READ 32
+-#endif
+-#if !ISPOWEROF2(MAX_HDR_READ)
+-#error MAX_HDR_READ is not a power of 2!
+-#endif
+-
+-#define MAX_RX_DATASZ 2048
+-
+-/* Maximum milliseconds to wait for F2 to come up */
+-#define DHD_WAIT_F2RDY 3000
+-
+-/* Bump up limit on waiting for HT to account for first startup;
+- * if the image is doing a CRC calculation before programming the PMU
+- * for HT availability, it could take a couple hundred ms more, so
+- * max out at a 1 second (1000000us).
+- */
+-#if (PMU_MAX_TRANSITION_DLY <= 1000000)
+-#undef PMU_MAX_TRANSITION_DLY
+-#define PMU_MAX_TRANSITION_DLY 1000000
+-#endif
+-
+-/* Value for ChipClockCSR during initial setup */
+-#define DHD_INIT_CLKCTL1 (SBSDIO_FORCE_HW_CLKREQ_OFF | \
+- SBSDIO_ALP_AVAIL_REQ)
+-#define DHD_INIT_CLKCTL2 (SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP)
+-
+-/* Flags for SDH calls */
+-#define F2SYNC (SDIO_REQ_4BYTE | SDIO_REQ_FIXED)
+-
+-/*
+- * Conversion of 802.1D priority to precedence level
+- */
+-#define PRIO2PREC(prio) \
+- (((prio) == PRIO_8021D_NONE || (prio) == PRIO_8021D_BE) ? \
+- ((prio^2)) : (prio))
+-
+-DHD_SPINWAIT_SLEEP_INIT(sdioh_spinwait_sleep);
+-extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf,
+- uint len);
+-
+-#ifdef DHD_DEBUG
+-/* Device console log buffer state */
+-typedef struct dhd_console {
+- uint count; /* Poll interval msec counter */
+- uint log_addr; /* Log struct address (fixed) */
+- hndrte_log_t log; /* Log struct (host copy) */
+- uint bufsize; /* Size of log buffer */
+- u8 *buf; /* Log buffer (host copy) */
+- uint last; /* Last buffer read index */
+-} dhd_console_t;
+-#endif /* DHD_DEBUG */
+-
+-/* misc chip info needed by some of the routines */
+-struct chip_info {
+- u32 chip;
+- u32 chiprev;
+- u32 cccorebase;
+- u32 ccrev;
+- u32 cccaps;
+- u32 buscorebase;
+- u32 buscorerev;
+- u32 buscoretype;
+- u32 ramcorebase;
+- u32 armcorebase;
+- u32 pmurev;
+- u32 ramsize;
+-};
+-
+-/* Private data for SDIO bus interaction */
+-typedef struct dhd_bus {
+- dhd_pub_t *dhd;
+-
+- bcmsdh_info_t *sdh; /* Handle for BCMSDH calls */
+- struct chip_info *ci; /* Chip info struct */
+- char *vars; /* Variables (from CIS and/or other) */
+- uint varsz; /* Size of variables buffer */
+- u32 sbaddr; /* Current SB window pointer (-1, invalid) */
+-
+- sdpcmd_regs_t *regs; /* Registers for SDIO core */
+- uint sdpcmrev; /* SDIO core revision */
+- uint armrev; /* CPU core revision */
+- uint ramrev; /* SOCRAM core revision */
+- u32 ramsize; /* Size of RAM in SOCRAM (bytes) */
+- u32 orig_ramsize; /* Size of RAM in SOCRAM (bytes) */
+-
+- u32 bus; /* gSPI or SDIO bus */
+- u32 hostintmask; /* Copy of Host Interrupt Mask */
+- u32 intstatus; /* Intstatus bits (events) pending */
+- bool dpc_sched; /* Indicates DPC schedule (intrpt rcvd) */
+- bool fcstate; /* State of dongle flow-control */
+-
+- u16 cl_devid; /* cached devid for dhdsdio_probe_attach() */
+- char *fw_path; /* module_param: path to firmware image */
+- char *nv_path; /* module_param: path to nvram vars file */
+- const char *nvram_params; /* user specified nvram params. */
+-
+- uint blocksize; /* Block size of SDIO transfers */
+- uint roundup; /* Max roundup limit */
+-
+- struct pktq txq; /* Queue length used for flow-control */
+- u8 flowcontrol; /* per prio flow control bitmask */
+- u8 tx_seq; /* Transmit sequence number (next) */
+- u8 tx_max; /* Maximum transmit sequence allowed */
+-
+- u8 hdrbuf[MAX_HDR_READ + DHD_SDALIGN];
+- u8 *rxhdr; /* Header of current rx frame (in hdrbuf) */
+- u16 nextlen; /* Next Read Len from last header */
+- u8 rx_seq; /* Receive sequence number (expected) */
+- bool rxskip; /* Skip receive (awaiting NAK ACK) */
+-
+- struct sk_buff *glomd; /* Packet containing glomming descriptor */
+- struct sk_buff *glom; /* Packet chain for glommed superframe */
+- uint glomerr; /* Glom packet read errors */
+-
+- u8 *rxbuf; /* Buffer for receiving control packets */
+- uint rxblen; /* Allocated length of rxbuf */
+- u8 *rxctl; /* Aligned pointer into rxbuf */
+- u8 *databuf; /* Buffer for receiving big glom packet */
+- u8 *dataptr; /* Aligned pointer into databuf */
+- uint rxlen; /* Length of valid data in buffer */
+-
+- u8 sdpcm_ver; /* Bus protocol reported by dongle */
+-
+- bool intr; /* Use interrupts */
+- bool poll; /* Use polling */
+- bool ipend; /* Device interrupt is pending */
+- bool intdis; /* Interrupts disabled by isr */
+- uint intrcount; /* Count of device interrupt callbacks */
+- uint lastintrs; /* Count as of last watchdog timer */
+- uint spurious; /* Count of spurious interrupts */
+- uint pollrate; /* Ticks between device polls */
+- uint polltick; /* Tick counter */
+- uint pollcnt; /* Count of active polls */
+-
+-#ifdef DHD_DEBUG
+- dhd_console_t console; /* Console output polling support */
+- uint console_addr; /* Console address from shared struct */
+-#endif /* DHD_DEBUG */
+-
+- uint regfails; /* Count of R_REG/W_REG failures */
+-
+- uint clkstate; /* State of sd and backplane clock(s) */
+- bool activity; /* Activity flag for clock down */
+- s32 idletime; /* Control for activity timeout */
+- s32 idlecount; /* Activity timeout counter */
+- s32 idleclock; /* How to set bus driver when idle */
+- s32 sd_divisor; /* Speed control to bus driver */
+- s32 sd_mode; /* Mode control to bus driver */
+- s32 sd_rxchain; /* If bcmsdh api accepts PKT chains */
+- bool use_rxchain; /* If dhd should use PKT chains */
+- bool sleeping; /* Is SDIO bus sleeping? */
+- bool rxflow_mode; /* Rx flow control mode */
+- bool rxflow; /* Is rx flow control on */
+- uint prev_rxlim_hit; /* Is prev rx limit exceeded
+- (per dpc schedule) */
+- bool alp_only; /* Don't use HT clock (ALP only) */
+-/* Field to decide if rx of control frames happen in rxbuf or lb-pool */
+- bool usebufpool;
+-
+-#ifdef SDTEST
+- /* external loopback */
+- bool ext_loop;
+- u8 loopid;
+-
+- /* pktgen configuration */
+- uint pktgen_freq; /* Ticks between bursts */
+- uint pktgen_count; /* Packets to send each burst */
+- uint pktgen_print; /* Bursts between count displays */
+- uint pktgen_total; /* Stop after this many */
+- uint pktgen_minlen; /* Minimum packet data len */
+- uint pktgen_maxlen; /* Maximum packet data len */
+- uint pktgen_mode; /* Configured mode: tx, rx, or echo */
+- uint pktgen_stop; /* Number of tx failures causing stop */
+-
+- /* active pktgen fields */
+- uint pktgen_tick; /* Tick counter for bursts */
+- uint pktgen_ptick; /* Burst counter for printing */
+- uint pktgen_sent; /* Number of test packets generated */
+- uint pktgen_rcvd; /* Number of test packets received */
+- uint pktgen_fail; /* Number of failed send attempts */
+- u16 pktgen_len; /* Length of next packet to send */
+-#endif /* SDTEST */
+-
+- /* Some additional counters */
+- uint tx_sderrs; /* Count of tx attempts with sd errors */
+- uint fcqueued; /* Tx packets that got queued */
+- uint rxrtx; /* Count of rtx requests (NAK to dongle) */
+- uint rx_toolong; /* Receive frames too long to receive */
+- uint rxc_errors; /* SDIO errors when reading control frames */
+- uint rx_hdrfail; /* SDIO errors on header reads */
+- uint rx_badhdr; /* Bad received headers (roosync?) */
+- uint rx_badseq; /* Mismatched rx sequence number */
+- uint fc_rcvd; /* Number of flow-control events received */
+- uint fc_xoff; /* Number which turned on flow-control */
+- uint fc_xon; /* Number which turned off flow-control */
+- uint rxglomfail; /* Failed deglom attempts */
+- uint rxglomframes; /* Number of glom frames (superframes) */
+- uint rxglompkts; /* Number of packets from glom frames */
+- uint f2rxhdrs; /* Number of header reads */
+- uint f2rxdata; /* Number of frame data reads */
+- uint f2txdata; /* Number of f2 frame writes */
+- uint f1regdata; /* Number of f1 register accesses */
+-
+- u8 *ctrl_frame_buf;
+- u32 ctrl_frame_len;
+- bool ctrl_frame_stat;
+-} dhd_bus_t;
+-
+-/* clkstate */
+-#define CLK_NONE 0
+-#define CLK_SDONLY 1
+-#define CLK_PENDING 2 /* Not used yet */
+-#define CLK_AVAIL 3
+-
+-#define DHD_NOPMU(dhd) (false)
+-
+-#ifdef DHD_DEBUG
+-static int qcount[NUMPRIO];
+-static int tx_packets[NUMPRIO];
+-#endif /* DHD_DEBUG */
+-
+-/* Deferred transmit */
+-const uint dhd_deferred_tx = 1;
+-
+-extern uint dhd_watchdog_ms;
+-extern void dhd_os_wd_timer(void *bus, uint wdtick);
+-
+-/* Tx/Rx bounds */
+-uint dhd_txbound;
+-uint dhd_rxbound;
+-uint dhd_txminmax;
+-
+-/* override the RAM size if possible */
+-#define DONGLE_MIN_MEMSIZE (128 * 1024)
+-int dhd_dongle_memsize;
+-
+-static bool dhd_alignctl;
+-
+-static bool sd1idle;
+-
+-static bool retrydata;
+-#define RETRYCHAN(chan) (((chan) == SDPCM_EVENT_CHANNEL) || retrydata)
+-
+-static const uint watermark = 8;
+-static const uint firstread = DHD_FIRSTREAD;
+-
+-#define HDATLEN (firstread - (SDPCM_HDRLEN))
+-
+-/* Retry count for register access failures */
+-static const uint retry_limit = 2;
+-
+-/* Force even SD lengths (some host controllers mess up on odd bytes) */
+-static bool forcealign;
+-
+-#define ALIGNMENT 4
+-
+-#if defined(OOB_INTR_ONLY) && defined(HW_OOB)
+-extern void bcmsdh_enable_hw_oob_intr(void *sdh, bool enable);
+-#endif
+-
+-#if defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD)
+-#error OOB_INTR_ONLY is NOT working with SDIO_ISR_THREAD
+-#endif /* defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD) */
+-#define PKTALIGN(_p, _len, _align) \
+- do { \
+- uint datalign; \
+- datalign = (unsigned long)((_p)->data); \
+- datalign = roundup(datalign, (_align)) - datalign; \
+- ASSERT(datalign < (_align)); \
+- ASSERT((_p)->len >= ((_len) + datalign)); \
+- if (datalign) \
+- skb_pull((_p), datalign); \
+- __skb_trim((_p), (_len)); \
+- } while (0)
+-
+-/* Limit on rounding up frames */
+-static const uint max_roundup = 512;
+-
+-/* Try doing readahead */
+-static bool dhd_readahead;
+-
+-/* To check if there's window offered */
+-#define DATAOK(bus) \
+- (((u8)(bus->tx_max - bus->tx_seq) != 0) && \
+- (((u8)(bus->tx_max - bus->tx_seq) & 0x80) == 0))
+-
+-/* Macros to get register read/write status */
+-/* NOTE: these assume a local dhdsdio_bus_t *bus! */
+-#define R_SDREG(regvar, regaddr, retryvar) \
+-do { \
+- retryvar = 0; \
+- do { \
+- regvar = R_REG(regaddr); \
+- } while (bcmsdh_regfail(bus->sdh) && (++retryvar <= retry_limit)); \
+- if (retryvar) { \
+- bus->regfails += (retryvar-1); \
+- if (retryvar > retry_limit) { \
+- DHD_ERROR(("%s: FAILED" #regvar "READ, LINE %d\n", \
+- __func__, __LINE__)); \
+- regvar = 0; \
+- } \
+- } \
+-} while (0)
+-
+-#define W_SDREG(regval, regaddr, retryvar) \
+-do { \
+- retryvar = 0; \
+- do { \
+- W_REG(regaddr, regval); \
+- } while (bcmsdh_regfail(bus->sdh) && (++retryvar <= retry_limit)); \
+- if (retryvar) { \
+- bus->regfails += (retryvar-1); \
+- if (retryvar > retry_limit) \
+- DHD_ERROR(("%s: FAILED REGISTER WRITE, LINE %d\n", \
+- __func__, __LINE__)); \
+- } \
+-} while (0)
+-
+-#define DHD_BUS SDIO_BUS
+-
+-#define PKT_AVAILABLE() (intstatus & I_HMB_FRAME_IND)
+-
+-#define HOSTINTMASK (I_HMB_SW_MASK | I_CHIPACTIVE)
+-
+-#ifdef SDTEST
+-static void dhdsdio_testrcv(dhd_bus_t *bus, void *pkt, uint seq);
+-static void dhdsdio_sdtest_set(dhd_bus_t *bus, bool start);
+-#endif
+-
+-#ifdef DHD_DEBUG
+-static int dhdsdio_checkdied(dhd_bus_t *bus, u8 *data, uint size);
+-static int dhdsdio_mem_dump(dhd_bus_t *bus);
+-#endif /* DHD_DEBUG */
+-static int dhdsdio_download_state(dhd_bus_t *bus, bool enter);
+-
+-static void dhdsdio_release(dhd_bus_t *bus);
+-static void dhdsdio_release_malloc(dhd_bus_t *bus);
+-static void dhdsdio_disconnect(void *ptr);
+-static bool dhdsdio_chipmatch(u16 chipid);
+-static bool dhdsdio_probe_attach(dhd_bus_t *bus, void *sdh,
+- void *regsva, u16 devid);
+-static bool dhdsdio_probe_malloc(dhd_bus_t *bus, void *sdh);
+-static bool dhdsdio_probe_init(dhd_bus_t *bus, void *sdh);
+-static void dhdsdio_release_dongle(dhd_bus_t *bus);
+-
+-static uint process_nvram_vars(char *varbuf, uint len);
+-
+-static void dhd_dongle_setmemsize(struct dhd_bus *bus, int mem_size);
+-static int dhd_bcmsdh_send_buf(dhd_bus_t *bus, u32 addr, uint fn,
+- uint flags, u8 *buf, uint nbytes,
+- struct sk_buff *pkt, bcmsdh_cmplt_fn_t complete,
+- void *handle);
+-
+-static bool dhdsdio_download_firmware(struct dhd_bus *bus, void *sdh);
+-static int _dhdsdio_download_firmware(struct dhd_bus *bus);
+-
+-static int dhdsdio_download_code_file(struct dhd_bus *bus, char *image_path);
+-static int dhdsdio_download_nvram(struct dhd_bus *bus);
+-#ifdef BCMEMBEDIMAGE
+-static int dhdsdio_download_code_array(struct dhd_bus *bus);
+-#endif
+-static void dhdsdio_chip_disablecore(bcmsdh_info_t *sdh, u32 corebase);
+-static int dhdsdio_chip_attach(struct dhd_bus *bus, void *regs);
+-static void dhdsdio_chip_resetcore(bcmsdh_info_t *sdh, u32 corebase);
+-static void dhdsdio_sdiod_drive_strength_init(struct dhd_bus *bus,
+- u32 drivestrength);
+-static void dhdsdio_chip_detach(struct dhd_bus *bus);
+-
+-/* Packet free applicable unconditionally for sdio and sdspi.
+- * Conditional if bufpool was present for gspi bus.
+- */
+-static void dhdsdio_pktfree2(dhd_bus_t *bus, struct sk_buff *pkt)
+-{
+- dhd_os_sdlock_rxq(bus->dhd);
+- if ((bus->bus != SPI_BUS) || bus->usebufpool)
+- bcm_pkt_buf_free_skb(pkt);
+- dhd_os_sdunlock_rxq(bus->dhd);
+-}
+-
+-static void dhd_dongle_setmemsize(struct dhd_bus *bus, int mem_size)
+-{
+- s32 min_size = DONGLE_MIN_MEMSIZE;
+- /* Restrict the memsize to user specified limit */
+- DHD_ERROR(("user: Restrict the dongle ram size to %d, min %d\n",
+- dhd_dongle_memsize, min_size));
+- if ((dhd_dongle_memsize > min_size) &&
+- (dhd_dongle_memsize < (s32) bus->orig_ramsize))
+- bus->ramsize = dhd_dongle_memsize;
+-}
+-
+-static int dhdsdio_set_siaddr_window(dhd_bus_t *bus, u32 address)
+-{
+- int err = 0;
+- bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
+- (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
+- if (!err)
+- bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRMID,
+- (address >> 16) & SBSDIO_SBADDRMID_MASK, &err);
+- if (!err)
+- bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRHIGH,
+- (address >> 24) & SBSDIO_SBADDRHIGH_MASK,
+- &err);
+- return err;
+-}
+-
+-/* Turn backplane clock on or off */
+-static int dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok)
+-{
+- int err;
+- u8 clkctl, clkreq, devctl;
+- bcmsdh_info_t *sdh;
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+-#if defined(OOB_INTR_ONLY)
+- pendok = false;
+-#endif
+- clkctl = 0;
+- sdh = bus->sdh;
+-
+- if (on) {
+- /* Request HT Avail */
+- clkreq =
+- bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ;
+-
+- if ((bus->ci->chip == BCM4329_CHIP_ID)
+- && (bus->ci->chiprev == 0))
+- clkreq |= SBSDIO_FORCE_ALP;
+-
+- bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
+- clkreq, &err);
+- if (err) {
+- DHD_ERROR(("%s: HT Avail request error: %d\n",
+- __func__, err));
+- return -EBADE;
+- }
+-
+- if (pendok && ((bus->ci->buscoretype == PCMCIA_CORE_ID)
+- && (bus->ci->buscorerev == 9))) {
+- u32 dummy, retries;
+- R_SDREG(dummy, &bus->regs->clockctlstatus, retries);
+- }
+-
+- /* Check current status */
+- clkctl =
+- bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
+- &err);
+- if (err) {
+- DHD_ERROR(("%s: HT Avail read error: %d\n",
+- __func__, err));
+- return -EBADE;
+- }
+-
+- /* Go to pending and await interrupt if appropriate */
+- if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) {
+- /* Allow only clock-available interrupt */
+- devctl =
+- bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
+- &err);
+- if (err) {
+- DHD_ERROR(("%s: Devctl error setting CA: %d\n",
+- __func__, err));
+- return -EBADE;
+- }
+-
+- devctl |= SBSDIO_DEVCTL_CA_INT_ONLY;
+- bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
+- devctl, &err);
+- DHD_INFO(("CLKCTL: set PENDING\n"));
+- bus->clkstate = CLK_PENDING;
+-
+- return 0;
+- } else if (bus->clkstate == CLK_PENDING) {
+- /* Cancel CA-only interrupt filter */
+- devctl =
+- bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
+- &err);
+- devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
+- bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
+- devctl, &err);
+- }
+-
+- /* Otherwise, wait here (polling) for HT Avail */
+- if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
+- SPINWAIT_SLEEP(sdioh_spinwait_sleep,
+- ((clkctl =
+- bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
+- SBSDIO_FUNC1_CHIPCLKCSR,
+- &err)),
+- !SBSDIO_CLKAV(clkctl, bus->alp_only)),
+- PMU_MAX_TRANSITION_DLY);
+- }
+- if (err) {
+- DHD_ERROR(("%s: HT Avail request error: %d\n",
+- __func__, err));
+- return -EBADE;
+- }
+- if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
+- DHD_ERROR(("%s: HT Avail timeout (%d): clkctl 0x%02x\n",
+- __func__, PMU_MAX_TRANSITION_DLY, clkctl));
+- return -EBADE;
+- }
+-
+- /* Mark clock available */
+- bus->clkstate = CLK_AVAIL;
+- DHD_INFO(("CLKCTL: turned ON\n"));
+-
+-#if defined(DHD_DEBUG)
+- if (bus->alp_only == true) {
+-#if !defined(BCMLXSDMMC)
+- if (!SBSDIO_ALPONLY(clkctl)) {
+- DHD_ERROR(("%s: HT Clock, when ALP Only\n",
+- __func__));
+- }
+-#endif /* !defined(BCMLXSDMMC) */
+- } else {
+- if (SBSDIO_ALPONLY(clkctl)) {
+- DHD_ERROR(("%s: HT Clock should be on.\n",
+- __func__));
+- }
+- }
+-#endif /* defined (DHD_DEBUG) */
+-
+- bus->activity = true;
+- } else {
+- clkreq = 0;
+-
+- if (bus->clkstate == CLK_PENDING) {
+- /* Cancel CA-only interrupt filter */
+- devctl =
+- bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
+- &err);
+- devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
+- bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
+- devctl, &err);
+- }
+-
+- bus->clkstate = CLK_SDONLY;
+- bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
+- clkreq, &err);
+- DHD_INFO(("CLKCTL: turned OFF\n"));
+- if (err) {
+- DHD_ERROR(("%s: Failed access turning clock off: %d\n",
+- __func__, err));
+- return -EBADE;
+- }
+- }
+- return 0;
+-}
+-
+-/* Change idle/active SD state */
+-static int dhdsdio_sdclk(dhd_bus_t *bus, bool on)
+-{
+- int err;
+- s32 iovalue;
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- if (on) {
+- if (bus->idleclock == DHD_IDLE_STOP) {
+- /* Turn on clock and restore mode */
+- iovalue = 1;
+- err = bcmsdh_iovar_op(bus->sdh, "sd_clock", NULL, 0,
+- &iovalue, sizeof(iovalue), true);
+- if (err) {
+- DHD_ERROR(("%s: error enabling sd_clock: %d\n",
+- __func__, err));
+- return -EBADE;
+- }
+-
+- iovalue = bus->sd_mode;
+- err = bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0,
+- &iovalue, sizeof(iovalue), true);
+- if (err) {
+- DHD_ERROR(("%s: error changing sd_mode: %d\n",
+- __func__, err));
+- return -EBADE;
+- }
+- } else if (bus->idleclock != DHD_IDLE_ACTIVE) {
+- /* Restore clock speed */
+- iovalue = bus->sd_divisor;
+- err = bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0,
+- &iovalue, sizeof(iovalue), true);
+- if (err) {
+- DHD_ERROR(("%s: error restoring sd_divisor: %d\n",
+- __func__, err));
+- return -EBADE;
+- }
+- }
+- bus->clkstate = CLK_SDONLY;
+- } else {
+- /* Stop or slow the SD clock itself */
+- if ((bus->sd_divisor == -1) || (bus->sd_mode == -1)) {
+- DHD_TRACE(("%s: can't idle clock, divisor %d mode %d\n",
+- __func__, bus->sd_divisor, bus->sd_mode));
+- return -EBADE;
+- }
+- if (bus->idleclock == DHD_IDLE_STOP) {
+- if (sd1idle) {
+- /* Change to SD1 mode and turn off clock */
+- iovalue = 1;
+- err =
+- bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL,
+- 0, &iovalue,
+- sizeof(iovalue), true);
+- if (err) {
+- DHD_ERROR(("%s: error changing sd_clock: %d\n",
+- __func__, err));
+- return -EBADE;
+- }
+- }
+-
+- iovalue = 0;
+- err = bcmsdh_iovar_op(bus->sdh, "sd_clock", NULL, 0,
+- &iovalue, sizeof(iovalue), true);
+- if (err) {
+- DHD_ERROR(("%s: error disabling sd_clock: %d\n",
+- __func__, err));
+- return -EBADE;
+- }
+- } else if (bus->idleclock != DHD_IDLE_ACTIVE) {
+- /* Set divisor to idle value */
+- iovalue = bus->idleclock;
+- err = bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0,
+- &iovalue, sizeof(iovalue), true);
+- if (err) {
+- DHD_ERROR(("%s: error changing sd_divisor: %d\n",
+- __func__, err));
+- return -EBADE;
+- }
+- }
+- bus->clkstate = CLK_NONE;
+- }
+-
+- return 0;
+-}
+-
+-/* Transition SD and backplane clock readiness */
+-static int dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok)
+-{
+-#ifdef DHD_DEBUG
+- uint oldstate = bus->clkstate;
+-#endif /* DHD_DEBUG */
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- /* Early exit if we're already there */
+- if (bus->clkstate == target) {
+- if (target == CLK_AVAIL) {
+- dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
+- bus->activity = true;
+- }
+- return 0;
+- }
+-
+- switch (target) {
+- case CLK_AVAIL:
+- /* Make sure SD clock is available */
+- if (bus->clkstate == CLK_NONE)
+- dhdsdio_sdclk(bus, true);
+- /* Now request HT Avail on the backplane */
+- dhdsdio_htclk(bus, true, pendok);
+- dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
+- bus->activity = true;
+- break;
+-
+- case CLK_SDONLY:
+- /* Remove HT request, or bring up SD clock */
+- if (bus->clkstate == CLK_NONE)
+- dhdsdio_sdclk(bus, true);
+- else if (bus->clkstate == CLK_AVAIL)
+- dhdsdio_htclk(bus, false, false);
+- else
+- DHD_ERROR(("dhdsdio_clkctl: request for %d -> %d\n",
+- bus->clkstate, target));
+- dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
+- break;
+-
+- case CLK_NONE:
+- /* Make sure to remove HT request */
+- if (bus->clkstate == CLK_AVAIL)
+- dhdsdio_htclk(bus, false, false);
+- /* Now remove the SD clock */
+- dhdsdio_sdclk(bus, false);
+- dhd_os_wd_timer(bus->dhd, 0);
+- break;
+- }
+-#ifdef DHD_DEBUG
+- DHD_INFO(("dhdsdio_clkctl: %d -> %d\n", oldstate, bus->clkstate));
+-#endif /* DHD_DEBUG */
+-
+- return 0;
+-}
+-
+-int dhdsdio_bussleep(dhd_bus_t *bus, bool sleep)
+-{
+- bcmsdh_info_t *sdh = bus->sdh;
+- sdpcmd_regs_t *regs = bus->regs;
+- uint retries = 0;
+-
+- DHD_INFO(("dhdsdio_bussleep: request %s (currently %s)\n",
+- (sleep ? "SLEEP" : "WAKE"),
+- (bus->sleeping ? "SLEEP" : "WAKE")));
+-
+- /* Done if we're already in the requested state */
+- if (sleep == bus->sleeping)
+- return 0;
+-
+- /* Going to sleep: set the alarm and turn off the lights... */
+- if (sleep) {
+- /* Don't sleep if something is pending */
+- if (bus->dpc_sched || bus->rxskip || pktq_len(&bus->txq))
+- return -EBUSY;
+-
+- /* Disable SDIO interrupts (no longer interested) */
+- bcmsdh_intr_disable(bus->sdh);
+-
+- /* Make sure the controller has the bus up */
+- dhdsdio_clkctl(bus, CLK_AVAIL, false);
+-
+- /* Tell device to start using OOB wakeup */
+- W_SDREG(SMB_USE_OOB, ®s->tosbmailbox, retries);
+- if (retries > retry_limit)
+- DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"));
+-
+- /* Turn off our contribution to the HT clock request */
+- dhdsdio_clkctl(bus, CLK_SDONLY, false);
+-
+- bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
+- SBSDIO_FORCE_HW_CLKREQ_OFF, NULL);
+-
+- /* Isolate the bus */
+- if (bus->ci->chip != BCM4329_CHIP_ID
+- && bus->ci->chip != BCM4319_CHIP_ID) {
+- bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
+- SBSDIO_DEVCTL_PADS_ISO, NULL);
+- }
+-
+- /* Change state */
+- bus->sleeping = true;
+-
+- } else {
+- /* Waking up: bus power up is ok, set local state */
+-
+- bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
+- 0, NULL);
+-
+- /* Force pad isolation off if possible
+- (in case power never toggled) */
+- if ((bus->ci->buscoretype == PCMCIA_CORE_ID)
+- && (bus->ci->buscorerev >= 10))
+- bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, 0,
+- NULL);
+-
+- /* Make sure the controller has the bus up */
+- dhdsdio_clkctl(bus, CLK_AVAIL, false);
+-
+- /* Send misc interrupt to indicate OOB not needed */
+- W_SDREG(0, ®s->tosbmailboxdata, retries);
+- if (retries <= retry_limit)
+- W_SDREG(SMB_DEV_INT, ®s->tosbmailbox, retries);
+-
+- if (retries > retry_limit)
+- DHD_ERROR(("CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"));
+-
+- /* Make sure we have SD bus access */
+- dhdsdio_clkctl(bus, CLK_SDONLY, false);
+-
+- /* Change state */
+- bus->sleeping = false;
+-
+- /* Enable interrupts again */
+- if (bus->intr && (bus->dhd->busstate == DHD_BUS_DATA)) {
+- bus->intdis = false;
+- bcmsdh_intr_enable(bus->sdh);
+- }
+- }
+-
+- return 0;
+-}
+-
+-#if defined(OOB_INTR_ONLY)
+-void dhd_enable_oob_intr(struct dhd_bus *bus, bool enable)
+-{
+-#if defined(HW_OOB)
+- bcmsdh_enable_hw_oob_intr(bus->sdh, enable);
+-#else
+- sdpcmd_regs_t *regs = bus->regs;
+- uint retries = 0;
+-
+- dhdsdio_clkctl(bus, CLK_AVAIL, false);
+- if (enable == true) {
+-
+- /* Tell device to start using OOB wakeup */
+- W_SDREG(SMB_USE_OOB, ®s->tosbmailbox, retries);
+- if (retries > retry_limit)
+- DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"));
+-
+- } else {
+- /* Send misc interrupt to indicate OOB not needed */
+- W_SDREG(0, ®s->tosbmailboxdata, retries);
+- if (retries <= retry_limit)
+- W_SDREG(SMB_DEV_INT, ®s->tosbmailbox, retries);
+- }
+-
+- /* Turn off our contribution to the HT clock request */
+- dhdsdio_clkctl(bus, CLK_SDONLY, false);
+-#endif /* !defined(HW_OOB) */
+-}
+-#endif /* defined(OOB_INTR_ONLY) */
+-
+-#define BUS_WAKE(bus) \
+- do { \
+- if ((bus)->sleeping) \
+- dhdsdio_bussleep((bus), false); \
+- } while (0);
+-
+-/* Writes a HW/SW header into the packet and sends it. */
+-/* Assumes: (a) header space already there, (b) caller holds lock */
+-static int dhdsdio_txpkt(dhd_bus_t *bus, struct sk_buff *pkt, uint chan,
+- bool free_pkt)
+-{
+- int ret;
+- u8 *frame;
+- u16 len, pad = 0;
+- u32 swheader;
+- uint retries = 0;
+- bcmsdh_info_t *sdh;
+- struct sk_buff *new;
+- int i;
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- sdh = bus->sdh;
+-
+- if (bus->dhd->dongle_reset) {
+- ret = -EPERM;
+- goto done;
+- }
+-
+- frame = (u8 *) (pkt->data);
+-
+- /* Add alignment padding, allocate new packet if needed */
+- pad = ((unsigned long)frame % DHD_SDALIGN);
+- if (pad) {
+- if (skb_headroom(pkt) < pad) {
+- DHD_INFO(("%s: insufficient headroom %d for %d pad\n",
+- __func__, skb_headroom(pkt), pad));
+- bus->dhd->tx_realloc++;
+- new = bcm_pkt_buf_get_skb(pkt->len + DHD_SDALIGN);
+- if (!new) {
+- DHD_ERROR(("%s: couldn't allocate new %d-byte "
+- "packet\n",
+- __func__, pkt->len + DHD_SDALIGN));
+- ret = -ENOMEM;
+- goto done;
+- }
+-
+- PKTALIGN(new, pkt->len, DHD_SDALIGN);
+- memcpy(new->data, pkt->data, pkt->len);
+- if (free_pkt)
+- bcm_pkt_buf_free_skb(pkt);
+- /* free the pkt if canned one is not used */
+- free_pkt = true;
+- pkt = new;
+- frame = (u8 *) (pkt->data);
+- ASSERT(((unsigned long)frame % DHD_SDALIGN) == 0);
+- pad = 0;
+- } else {
+- skb_push(pkt, pad);
+- frame = (u8 *) (pkt->data);
+-
+- ASSERT((pad + SDPCM_HDRLEN) <= (int)(pkt->len));
+- memset(frame, 0, pad + SDPCM_HDRLEN);
+- }
+- }
+- ASSERT(pad < DHD_SDALIGN);
+-
+- /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
+- len = (u16) (pkt->len);
+- *(u16 *) frame = cpu_to_le16(len);
+- *(((u16 *) frame) + 1) = cpu_to_le16(~len);
+-
+- /* Software tag: channel, sequence number, data offset */
+- swheader =
+- ((chan << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK) | bus->tx_seq |
+- (((pad +
+- SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
+-
+- put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN);
+- put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
+-
+-#ifdef DHD_DEBUG
+- tx_packets[pkt->priority]++;
+- if (DHD_BYTES_ON() &&
+- (((DHD_CTL_ON() && (chan == SDPCM_CONTROL_CHANNEL)) ||
+- (DHD_DATA_ON() && (chan != SDPCM_CONTROL_CHANNEL))))) {
+- printk(KERN_DEBUG "Tx Frame:\n");
+- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, frame, len);
+- } else if (DHD_HDRS_ON()) {
+- printk(KERN_DEBUG "TxHdr:\n");
+- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
+- frame, min_t(u16, len, 16));
+- }
+-#endif
+-
+- /* Raise len to next SDIO block to eliminate tail command */
+- if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
+- u16 pad = bus->blocksize - (len % bus->blocksize);
+- if ((pad <= bus->roundup) && (pad < bus->blocksize))
+-#ifdef NOTUSED
+- if (pad <= skb_tailroom(pkt))
+-#endif /* NOTUSED */
+- len += pad;
+- } else if (len % DHD_SDALIGN) {
+- len += DHD_SDALIGN - (len % DHD_SDALIGN);
+- }
+-
+- /* Some controllers have trouble with odd bytes -- round to even */
+- if (forcealign && (len & (ALIGNMENT - 1))) {
+-#ifdef NOTUSED
+- if (skb_tailroom(pkt))
+-#endif
+- len = roundup(len, ALIGNMENT);
+-#ifdef NOTUSED
+- else
+- DHD_ERROR(("%s: sending unrounded %d-byte packet\n",
+- __func__, len));
+-#endif
+- }
+-
+- do {
+- ret =
+- dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2,
+- F2SYNC, frame, len, pkt, NULL, NULL);
+- bus->f2txdata++;
+- ASSERT(ret != -BCME_PENDING);
+-
+- if (ret < 0) {
+- /* On failure, abort the command
+- and terminate the frame */
+- DHD_INFO(("%s: sdio error %d, abort command and "
+- "terminate frame.\n", __func__, ret));
+- bus->tx_sderrs++;
+-
+- bcmsdh_abort(sdh, SDIO_FUNC_2);
+- bcmsdh_cfg_write(sdh, SDIO_FUNC_1,
+- SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM,
+- NULL);
+- bus->f1regdata++;
+-
+- for (i = 0; i < 3; i++) {
+- u8 hi, lo;
+- hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
+- SBSDIO_FUNC1_WFRAMEBCHI,
+- NULL);
+- lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
+- SBSDIO_FUNC1_WFRAMEBCLO,
+- NULL);
+- bus->f1regdata += 2;
+- if ((hi == 0) && (lo == 0))
+- break;
+- }
+-
+- }
+- if (ret == 0)
+- bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
+-
+- } while ((ret < 0) && retrydata && retries++ < TXRETRIES);
+-
+-done:
+- /* restore pkt buffer pointer before calling tx complete routine */
+- skb_pull(pkt, SDPCM_HDRLEN + pad);
+- dhd_os_sdunlock(bus->dhd);
+- dhd_txcomplete(bus->dhd, pkt, ret != 0);
+- dhd_os_sdlock(bus->dhd);
+-
+- if (free_pkt)
+- bcm_pkt_buf_free_skb(pkt);
+-
+- return ret;
+-}
+-
+-int dhd_bus_txdata(struct dhd_bus *bus, struct sk_buff *pkt)
+-{
+- int ret = -EBADE;
+- uint datalen, prec;
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- datalen = pkt->len;
+-
+-#ifdef SDTEST
+- /* Push the test header if doing loopback */
+- if (bus->ext_loop) {
+- u8 *data;
+- skb_push(pkt, SDPCM_TEST_HDRLEN);
+- data = pkt->data;
+- *data++ = SDPCM_TEST_ECHOREQ;
+- *data++ = (u8) bus->loopid++;
+- *data++ = (datalen >> 0);
+- *data++ = (datalen >> 8);
+- datalen += SDPCM_TEST_HDRLEN;
+- }
+-#endif /* SDTEST */
+-
+- /* Add space for the header */
+- skb_push(pkt, SDPCM_HDRLEN);
+- ASSERT(IS_ALIGNED((unsigned long)(pkt->data), 2));
+-
+- prec = PRIO2PREC((pkt->priority & PRIOMASK));
+-
+- /* Check for existing queue, current flow-control,
+- pending event, or pending clock */
+- if (dhd_deferred_tx || bus->fcstate || pktq_len(&bus->txq)
+- || bus->dpc_sched || (!DATAOK(bus))
+- || (bus->flowcontrol & NBITVAL(prec))
+- || (bus->clkstate != CLK_AVAIL)) {
+- DHD_TRACE(("%s: deferring pktq len %d\n", __func__,
+- pktq_len(&bus->txq)));
+- bus->fcqueued++;
+-
+- /* Priority based enq */
+- dhd_os_sdlock_txq(bus->dhd);
+- if (dhd_prec_enq(bus->dhd, &bus->txq, pkt, prec) == false) {
+- skb_pull(pkt, SDPCM_HDRLEN);
+- dhd_txcomplete(bus->dhd, pkt, false);
+- bcm_pkt_buf_free_skb(pkt);
+- DHD_ERROR(("%s: out of bus->txq !!!\n", __func__));
+- ret = -ENOSR;
+- } else {
+- ret = 0;
+- }
+- dhd_os_sdunlock_txq(bus->dhd);
+-
+- if (pktq_len(&bus->txq) >= TXHI)
+- dhd_txflowcontrol(bus->dhd, 0, ON);
+-
+-#ifdef DHD_DEBUG
+- if (pktq_plen(&bus->txq, prec) > qcount[prec])
+- qcount[prec] = pktq_plen(&bus->txq, prec);
+-#endif
+- /* Schedule DPC if needed to send queued packet(s) */
+- if (dhd_deferred_tx && !bus->dpc_sched) {
+- bus->dpc_sched = true;
+- dhd_sched_dpc(bus->dhd);
+- }
+- } else {
+- /* Lock: we're about to use shared data/code (and SDIO) */
+- dhd_os_sdlock(bus->dhd);
+-
+- /* Otherwise, send it now */
+- BUS_WAKE(bus);
+- /* Make sure back plane ht clk is on, no pending allowed */
+- dhdsdio_clkctl(bus, CLK_AVAIL, true);
+-
+-#ifndef SDTEST
+- DHD_TRACE(("%s: calling txpkt\n", __func__));
+- ret = dhdsdio_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true);
+-#else
+- ret = dhdsdio_txpkt(bus, pkt,
+- (bus->ext_loop ? SDPCM_TEST_CHANNEL :
+- SDPCM_DATA_CHANNEL), true);
+-#endif
+- if (ret)
+- bus->dhd->tx_errors++;
+- else
+- bus->dhd->dstats.tx_bytes += datalen;
+-
+- if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
+- bus->activity = false;
+- dhdsdio_clkctl(bus, CLK_NONE, true);
+- }
+-
+- dhd_os_sdunlock(bus->dhd);
+- }
+-
+- return ret;
+-}
+-
+-static uint dhdsdio_sendfromq(dhd_bus_t *bus, uint maxframes)
+-{
+- struct sk_buff *pkt;
+- u32 intstatus = 0;
+- uint retries = 0;
+- int ret = 0, prec_out;
+- uint cnt = 0;
+- uint datalen;
+- u8 tx_prec_map;
+-
+- dhd_pub_t *dhd = bus->dhd;
+- sdpcmd_regs_t *regs = bus->regs;
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- tx_prec_map = ~bus->flowcontrol;
+-
+- /* Send frames until the limit or some other event */
+- for (cnt = 0; (cnt < maxframes) && DATAOK(bus); cnt++) {
+- dhd_os_sdlock_txq(bus->dhd);
+- pkt = bcm_pktq_mdeq(&bus->txq, tx_prec_map, &prec_out);
+- if (pkt == NULL) {
+- dhd_os_sdunlock_txq(bus->dhd);
+- break;
+- }
+- dhd_os_sdunlock_txq(bus->dhd);
+- datalen = pkt->len - SDPCM_HDRLEN;
+-
+-#ifndef SDTEST
+- ret = dhdsdio_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true);
+-#else
+- ret = dhdsdio_txpkt(bus, pkt,
+- (bus->ext_loop ? SDPCM_TEST_CHANNEL :
+- SDPCM_DATA_CHANNEL), true);
+-#endif
+- if (ret)
+- bus->dhd->tx_errors++;
+- else
+- bus->dhd->dstats.tx_bytes += datalen;
+-
+- /* In poll mode, need to check for other events */
+- if (!bus->intr && cnt) {
+- /* Check device status, signal pending interrupt */
+- R_SDREG(intstatus, ®s->intstatus, retries);
+- bus->f2txdata++;
+- if (bcmsdh_regfail(bus->sdh))
+- break;
+- if (intstatus & bus->hostintmask)
+- bus->ipend = true;
+- }
+- }
+-
+- /* Deflow-control stack if needed */
+- if (dhd->up && (dhd->busstate == DHD_BUS_DATA) &&
+- dhd->txoff && (pktq_len(&bus->txq) < TXLOW))
+- dhd_txflowcontrol(dhd, 0, OFF);
+-
+- return cnt;
+-}
+-
+-int dhd_bus_txctl(struct dhd_bus *bus, unsigned char *msg, uint msglen)
+-{
+- u8 *frame;
+- u16 len;
+- u32 swheader;
+- uint retries = 0;
+- bcmsdh_info_t *sdh = bus->sdh;
+- u8 doff = 0;
+- int ret = -1;
+- int i;
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- if (bus->dhd->dongle_reset)
+- return -EIO;
+-
+- /* Back the pointer to make a room for bus header */
+- frame = msg - SDPCM_HDRLEN;
+- len = (msglen += SDPCM_HDRLEN);
+-
+- /* Add alignment padding (optional for ctl frames) */
+- if (dhd_alignctl) {
+- doff = ((unsigned long)frame % DHD_SDALIGN);
+- if (doff) {
+- frame -= doff;
+- len += doff;
+- msglen += doff;
+- memset(frame, 0, doff + SDPCM_HDRLEN);
+- }
+- ASSERT(doff < DHD_SDALIGN);
+- }
+- doff += SDPCM_HDRLEN;
+-
+- /* Round send length to next SDIO block */
+- if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
+- u16 pad = bus->blocksize - (len % bus->blocksize);
+- if ((pad <= bus->roundup) && (pad < bus->blocksize))
+- len += pad;
+- } else if (len % DHD_SDALIGN) {
+- len += DHD_SDALIGN - (len % DHD_SDALIGN);
+- }
+-
+- /* Satisfy length-alignment requirements */
+- if (forcealign && (len & (ALIGNMENT - 1)))
+- len = roundup(len, ALIGNMENT);
+-
+- ASSERT(IS_ALIGNED((unsigned long)frame, 2));
+-
+- /* Need to lock here to protect txseq and SDIO tx calls */
+- dhd_os_sdlock(bus->dhd);
+-
+- BUS_WAKE(bus);
+-
+- /* Make sure backplane clock is on */
+- dhdsdio_clkctl(bus, CLK_AVAIL, false);
+-
+- /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
+- *(u16 *) frame = cpu_to_le16((u16) msglen);
+- *(((u16 *) frame) + 1) = cpu_to_le16(~msglen);
+-
+- /* Software tag: channel, sequence number, data offset */
+- swheader =
+- ((SDPCM_CONTROL_CHANNEL << SDPCM_CHANNEL_SHIFT) &
+- SDPCM_CHANNEL_MASK)
+- | bus->tx_seq | ((doff << SDPCM_DOFFSET_SHIFT) &
+- SDPCM_DOFFSET_MASK);
+- put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN);
+- put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
+-
+- if (!DATAOK(bus)) {
+- DHD_INFO(("%s: No bus credit bus->tx_max %d, bus->tx_seq %d\n",
+- __func__, bus->tx_max, bus->tx_seq));
+- bus->ctrl_frame_stat = true;
+- /* Send from dpc */
+- bus->ctrl_frame_buf = frame;
+- bus->ctrl_frame_len = len;
+-
+- dhd_wait_for_event(bus->dhd, &bus->ctrl_frame_stat);
+-
+- if (bus->ctrl_frame_stat == false) {
+- DHD_INFO(("%s: ctrl_frame_stat == false\n", __func__));
+- ret = 0;
+- } else {
+- DHD_INFO(("%s: ctrl_frame_stat == true\n", __func__));
+- ret = -1;
+- }
+- }
+-
+- if (ret == -1) {
+-#ifdef DHD_DEBUG
+- if (DHD_BYTES_ON() && DHD_CTL_ON()) {
+- printk(KERN_DEBUG "Tx Frame:\n");
+- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
+- frame, len);
+- } else if (DHD_HDRS_ON()) {
+- printk(KERN_DEBUG "TxHdr:\n");
+- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
+- frame, min_t(u16, len, 16));
+- }
+-#endif
+-
+- do {
+- bus->ctrl_frame_stat = false;
+- ret =
+- dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh),
+- SDIO_FUNC_2, F2SYNC, frame, len,
+- NULL, NULL, NULL);
+-
+- ASSERT(ret != -BCME_PENDING);
+-
+- if (ret < 0) {
+- /* On failure, abort the command and
+- terminate the frame */
+- DHD_INFO(("%s: sdio error %d, abort command and terminate frame.\n",
+- __func__, ret));
+- bus->tx_sderrs++;
+-
+- bcmsdh_abort(sdh, SDIO_FUNC_2);
+-
+- bcmsdh_cfg_write(sdh, SDIO_FUNC_1,
+- SBSDIO_FUNC1_FRAMECTRL,
+- SFC_WF_TERM, NULL);
+- bus->f1regdata++;
+-
+- for (i = 0; i < 3; i++) {
+- u8 hi, lo;
+- hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
+- SBSDIO_FUNC1_WFRAMEBCHI,
+- NULL);
+- lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
+- SBSDIO_FUNC1_WFRAMEBCLO,
+- NULL);
+- bus->f1regdata += 2;
+- if ((hi == 0) && (lo == 0))
+- break;
+- }
+-
+- }
+- if (ret == 0) {
+- bus->tx_seq =
+- (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
+- }
+- } while ((ret < 0) && retries++ < TXRETRIES);
+- }
+-
+- if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
+- bus->activity = false;
+- dhdsdio_clkctl(bus, CLK_NONE, true);
+- }
+-
+- dhd_os_sdunlock(bus->dhd);
+-
+- if (ret)
+- bus->dhd->tx_ctlerrs++;
+- else
+- bus->dhd->tx_ctlpkts++;
+-
+- return ret ? -EIO : 0;
+-}
+-
+-int dhd_bus_rxctl(struct dhd_bus *bus, unsigned char *msg, uint msglen)
+-{
+- int timeleft;
+- uint rxlen = 0;
+- bool pending;
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- if (bus->dhd->dongle_reset)
+- return -EIO;
+-
+- /* Wait until control frame is available */
+- timeleft = dhd_os_ioctl_resp_wait(bus->dhd, &bus->rxlen, &pending);
+-
+- dhd_os_sdlock(bus->dhd);
+- rxlen = bus->rxlen;
+- memcpy(msg, bus->rxctl, min(msglen, rxlen));
+- bus->rxlen = 0;
+- dhd_os_sdunlock(bus->dhd);
+-
+- if (rxlen) {
+- DHD_CTL(("%s: resumed on rxctl frame, got %d expected %d\n",
+- __func__, rxlen, msglen));
+- } else if (timeleft == 0) {
+- DHD_ERROR(("%s: resumed on timeout\n", __func__));
+-#ifdef DHD_DEBUG
+- dhd_os_sdlock(bus->dhd);
+- dhdsdio_checkdied(bus, NULL, 0);
+- dhd_os_sdunlock(bus->dhd);
+-#endif /* DHD_DEBUG */
+- } else if (pending == true) {
+- DHD_CTL(("%s: cancelled\n", __func__));
+- return -ERESTARTSYS;
+- } else {
+- DHD_CTL(("%s: resumed for unknown reason?\n", __func__));
+-#ifdef DHD_DEBUG
+- dhd_os_sdlock(bus->dhd);
+- dhdsdio_checkdied(bus, NULL, 0);
+- dhd_os_sdunlock(bus->dhd);
+-#endif /* DHD_DEBUG */
+- }
+-
+- if (rxlen)
+- bus->dhd->rx_ctlpkts++;
+- else
+- bus->dhd->rx_ctlerrs++;
+-
+- return rxlen ? (int)rxlen : -ETIMEDOUT;
+-}
+-
+-/* IOVar table */
+-enum {
+- IOV_INTR = 1,
+- IOV_POLLRATE,
+- IOV_SDREG,
+- IOV_SBREG,
+- IOV_SDCIS,
+- IOV_MEMBYTES,
+- IOV_MEMSIZE,
+-#ifdef DHD_DEBUG
+- IOV_CHECKDIED,
+-#endif
+- IOV_DOWNLOAD,
+- IOV_FORCEEVEN,
+- IOV_SDIOD_DRIVE,
+- IOV_READAHEAD,
+- IOV_SDRXCHAIN,
+- IOV_ALIGNCTL,
+- IOV_SDALIGN,
+- IOV_DEVRESET,
+- IOV_CPU,
+-#ifdef SDTEST
+- IOV_PKTGEN,
+- IOV_EXTLOOP,
+-#endif /* SDTEST */
+- IOV_SPROM,
+- IOV_TXBOUND,
+- IOV_RXBOUND,
+- IOV_TXMINMAX,
+- IOV_IDLETIME,
+- IOV_IDLECLOCK,
+- IOV_SD1IDLE,
+- IOV_SLEEP,
+- IOV_VARS
+-};
+-
+-const bcm_iovar_t dhdsdio_iovars[] = {
+- {"intr", IOV_INTR, 0, IOVT_BOOL, 0},
+- {"sleep", IOV_SLEEP, 0, IOVT_BOOL, 0},
+- {"pollrate", IOV_POLLRATE, 0, IOVT_UINT32, 0},
+- {"idletime", IOV_IDLETIME, 0, IOVT_INT32, 0},
+- {"idleclock", IOV_IDLECLOCK, 0, IOVT_INT32, 0},
+- {"sd1idle", IOV_SD1IDLE, 0, IOVT_BOOL, 0},
+- {"membytes", IOV_MEMBYTES, 0, IOVT_BUFFER, 2 * sizeof(int)},
+- {"memsize", IOV_MEMSIZE, 0, IOVT_UINT32, 0},
+- {"download", IOV_DOWNLOAD, 0, IOVT_BOOL, 0},
+- {"vars", IOV_VARS, 0, IOVT_BUFFER, 0},
+- {"sdiod_drive", IOV_SDIOD_DRIVE, 0, IOVT_UINT32, 0},
+- {"readahead", IOV_READAHEAD, 0, IOVT_BOOL, 0},
+- {"sdrxchain", IOV_SDRXCHAIN, 0, IOVT_BOOL, 0},
+- {"alignctl", IOV_ALIGNCTL, 0, IOVT_BOOL, 0},
+- {"sdalign", IOV_SDALIGN, 0, IOVT_BOOL, 0},
+- {"devreset", IOV_DEVRESET, 0, IOVT_BOOL, 0},
+-#ifdef DHD_DEBUG
+- {"sdreg", IOV_SDREG, 0, IOVT_BUFFER, sizeof(sdreg_t)}
+- ,
+- {"sbreg", IOV_SBREG, 0, IOVT_BUFFER, sizeof(sdreg_t)}
+- ,
+- {"sd_cis", IOV_SDCIS, 0, IOVT_BUFFER, DHD_IOCTL_MAXLEN}
+- ,
+- {"forcealign", IOV_FORCEEVEN, 0, IOVT_BOOL, 0}
+- ,
+- {"txbound", IOV_TXBOUND, 0, IOVT_UINT32, 0}
+- ,
+- {"rxbound", IOV_RXBOUND, 0, IOVT_UINT32, 0}
+- ,
+- {"txminmax", IOV_TXMINMAX, 0, IOVT_UINT32, 0}
+- ,
+- {"cpu", IOV_CPU, 0, IOVT_BOOL, 0}
+- ,
+-#ifdef DHD_DEBUG
+- {"checkdied", IOV_CHECKDIED, 0, IOVT_BUFFER, 0}
+- ,
+-#endif /* DHD_DEBUG */
+-#endif /* DHD_DEBUG */
+-#ifdef SDTEST
+- {"extloop", IOV_EXTLOOP, 0, IOVT_BOOL, 0}
+- ,
+- {"pktgen", IOV_PKTGEN, 0, IOVT_BUFFER, sizeof(dhd_pktgen_t)}
+- ,
+-#endif /* SDTEST */
+-
+- {NULL, 0, 0, 0, 0}
+-};
+-
+-static void
+-dhd_dump_pct(struct bcmstrbuf *strbuf, char *desc, uint num, uint div)
+-{
+- uint q1, q2;
+-
+- if (!div) {
+- bcm_bprintf(strbuf, "%s N/A", desc);
+- } else {
+- q1 = num / div;
+- q2 = (100 * (num - (q1 * div))) / div;
+- bcm_bprintf(strbuf, "%s %d.%02d", desc, q1, q2);
+- }
+-}
+-
+-void dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf)
+-{
+- dhd_bus_t *bus = dhdp->bus;
+-
+- bcm_bprintf(strbuf, "Bus SDIO structure:\n");
+- bcm_bprintf(strbuf,
+- "hostintmask 0x%08x intstatus 0x%08x sdpcm_ver %d\n",
+- bus->hostintmask, bus->intstatus, bus->sdpcm_ver);
+- bcm_bprintf(strbuf,
+- "fcstate %d qlen %d tx_seq %d, max %d, rxskip %d rxlen %d rx_seq %d\n",
+- bus->fcstate, pktq_len(&bus->txq), bus->tx_seq, bus->tx_max,
+- bus->rxskip, bus->rxlen, bus->rx_seq);
+- bcm_bprintf(strbuf, "intr %d intrcount %d lastintrs %d spurious %d\n",
+- bus->intr, bus->intrcount, bus->lastintrs, bus->spurious);
+- bcm_bprintf(strbuf, "pollrate %d pollcnt %d regfails %d\n",
+- bus->pollrate, bus->pollcnt, bus->regfails);
+-
+- bcm_bprintf(strbuf, "\nAdditional counters:\n");
+- bcm_bprintf(strbuf,
+- "tx_sderrs %d fcqueued %d rxrtx %d rx_toolong %d rxc_errors %d\n",
+- bus->tx_sderrs, bus->fcqueued, bus->rxrtx, bus->rx_toolong,
+- bus->rxc_errors);
+- bcm_bprintf(strbuf, "rx_hdrfail %d badhdr %d badseq %d\n",
+- bus->rx_hdrfail, bus->rx_badhdr, bus->rx_badseq);
+- bcm_bprintf(strbuf, "fc_rcvd %d, fc_xoff %d, fc_xon %d\n", bus->fc_rcvd,
+- bus->fc_xoff, bus->fc_xon);
+- bcm_bprintf(strbuf, "rxglomfail %d, rxglomframes %d, rxglompkts %d\n",
+- bus->rxglomfail, bus->rxglomframes, bus->rxglompkts);
+- bcm_bprintf(strbuf, "f2rx (hdrs/data) %d (%d/%d), f2tx %d f1regs %d\n",
+- (bus->f2rxhdrs + bus->f2rxdata), bus->f2rxhdrs,
+- bus->f2rxdata, bus->f2txdata, bus->f1regdata);
+- {
+- dhd_dump_pct(strbuf, "\nRx: pkts/f2rd", bus->dhd->rx_packets,
+- (bus->f2rxhdrs + bus->f2rxdata));
+- dhd_dump_pct(strbuf, ", pkts/f1sd", bus->dhd->rx_packets,
+- bus->f1regdata);
+- dhd_dump_pct(strbuf, ", pkts/sd", bus->dhd->rx_packets,
+- (bus->f2rxhdrs + bus->f2rxdata + bus->f1regdata));
+- dhd_dump_pct(strbuf, ", pkts/int", bus->dhd->rx_packets,
+- bus->intrcount);
+- bcm_bprintf(strbuf, "\n");
+-
+- dhd_dump_pct(strbuf, "Rx: glom pct", (100 * bus->rxglompkts),
+- bus->dhd->rx_packets);
+- dhd_dump_pct(strbuf, ", pkts/glom", bus->rxglompkts,
+- bus->rxglomframes);
+- bcm_bprintf(strbuf, "\n");
+-
+- dhd_dump_pct(strbuf, "Tx: pkts/f2wr", bus->dhd->tx_packets,
+- bus->f2txdata);
+- dhd_dump_pct(strbuf, ", pkts/f1sd", bus->dhd->tx_packets,
+- bus->f1regdata);
+- dhd_dump_pct(strbuf, ", pkts/sd", bus->dhd->tx_packets,
+- (bus->f2txdata + bus->f1regdata));
+- dhd_dump_pct(strbuf, ", pkts/int", bus->dhd->tx_packets,
+- bus->intrcount);
+- bcm_bprintf(strbuf, "\n");
+-
+- dhd_dump_pct(strbuf, "Total: pkts/f2rw",
+- (bus->dhd->tx_packets + bus->dhd->rx_packets),
+- (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata));
+- dhd_dump_pct(strbuf, ", pkts/f1sd",
+- (bus->dhd->tx_packets + bus->dhd->rx_packets),
+- bus->f1regdata);
+- dhd_dump_pct(strbuf, ", pkts/sd",
+- (bus->dhd->tx_packets + bus->dhd->rx_packets),
+- (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata +
+- bus->f1regdata));
+- dhd_dump_pct(strbuf, ", pkts/int",
+- (bus->dhd->tx_packets + bus->dhd->rx_packets),
+- bus->intrcount);
+- bcm_bprintf(strbuf, "\n\n");
+- }
+-
+-#ifdef SDTEST
+- if (bus->pktgen_count) {
+- bcm_bprintf(strbuf, "pktgen config and count:\n");
+- bcm_bprintf(strbuf,
+- "freq %d count %d print %d total %d min %d len %d\n",
+- bus->pktgen_freq, bus->pktgen_count,
+- bus->pktgen_print, bus->pktgen_total,
+- bus->pktgen_minlen, bus->pktgen_maxlen);
+- bcm_bprintf(strbuf, "send attempts %d rcvd %d fail %d\n",
+- bus->pktgen_sent, bus->pktgen_rcvd,
+- bus->pktgen_fail);
+- }
+-#endif /* SDTEST */
+-#ifdef DHD_DEBUG
+- bcm_bprintf(strbuf, "dpc_sched %d host interrupt%spending\n",
+- bus->dpc_sched,
+- (bcmsdh_intr_pending(bus->sdh) ? " " : " not "));
+- bcm_bprintf(strbuf, "blocksize %d roundup %d\n", bus->blocksize,
+- bus->roundup);
+-#endif /* DHD_DEBUG */
+- bcm_bprintf(strbuf,
+- "clkstate %d activity %d idletime %d idlecount %d sleeping %d\n",
+- bus->clkstate, bus->activity, bus->idletime, bus->idlecount,
+- bus->sleeping);
+-}
+-
+-void dhd_bus_clearcounts(dhd_pub_t *dhdp)
+-{
+- dhd_bus_t *bus = (dhd_bus_t *) dhdp->bus;
+-
+- bus->intrcount = bus->lastintrs = bus->spurious = bus->regfails = 0;
+- bus->rxrtx = bus->rx_toolong = bus->rxc_errors = 0;
+- bus->rx_hdrfail = bus->rx_badhdr = bus->rx_badseq = 0;
+- bus->tx_sderrs = bus->fc_rcvd = bus->fc_xoff = bus->fc_xon = 0;
+- bus->rxglomfail = bus->rxglomframes = bus->rxglompkts = 0;
+- bus->f2rxhdrs = bus->f2rxdata = bus->f2txdata = bus->f1regdata = 0;
+-}
+-
+-#ifdef SDTEST
+-static int dhdsdio_pktgen_get(dhd_bus_t *bus, u8 *arg)
+-{
+- dhd_pktgen_t pktgen;
+-
+- pktgen.version = DHD_PKTGEN_VERSION;
+- pktgen.freq = bus->pktgen_freq;
+- pktgen.count = bus->pktgen_count;
+- pktgen.print = bus->pktgen_print;
+- pktgen.total = bus->pktgen_total;
+- pktgen.minlen = bus->pktgen_minlen;
+- pktgen.maxlen = bus->pktgen_maxlen;
+- pktgen.numsent = bus->pktgen_sent;
+- pktgen.numrcvd = bus->pktgen_rcvd;
+- pktgen.numfail = bus->pktgen_fail;
+- pktgen.mode = bus->pktgen_mode;
+- pktgen.stop = bus->pktgen_stop;
+-
+- memcpy(arg, &pktgen, sizeof(pktgen));
+-
+- return 0;
+-}
+-
+-static int dhdsdio_pktgen_set(dhd_bus_t *bus, u8 *arg)
+-{
+- dhd_pktgen_t pktgen;
+- uint oldcnt, oldmode;
+-
+- memcpy(&pktgen, arg, sizeof(pktgen));
+- if (pktgen.version != DHD_PKTGEN_VERSION)
+- return -EINVAL;
+-
+- oldcnt = bus->pktgen_count;
+- oldmode = bus->pktgen_mode;
+-
+- bus->pktgen_freq = pktgen.freq;
+- bus->pktgen_count = pktgen.count;
+- bus->pktgen_print = pktgen.print;
+- bus->pktgen_total = pktgen.total;
+- bus->pktgen_minlen = pktgen.minlen;
+- bus->pktgen_maxlen = pktgen.maxlen;
+- bus->pktgen_mode = pktgen.mode;
+- bus->pktgen_stop = pktgen.stop;
+-
+- bus->pktgen_tick = bus->pktgen_ptick = 0;
+- bus->pktgen_len = max(bus->pktgen_len, bus->pktgen_minlen);
+- bus->pktgen_len = min(bus->pktgen_len, bus->pktgen_maxlen);
+-
+- /* Clear counts for a new pktgen (mode change, or was stopped) */
+- if (bus->pktgen_count && (!oldcnt || oldmode != bus->pktgen_mode))
+- bus->pktgen_sent = bus->pktgen_rcvd = bus->pktgen_fail = 0;
+-
+- return 0;
+-}
+-#endif /* SDTEST */
+-
+-static int
+-dhdsdio_membytes(dhd_bus_t *bus, bool write, u32 address, u8 *data,
+- uint size)
+-{
+- int bcmerror = 0;
+- u32 sdaddr;
+- uint dsize;
+-
+- /* Determine initial transfer parameters */
+- sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK;
+- if ((sdaddr + size) & SBSDIO_SBWINDOW_MASK)
+- dsize = (SBSDIO_SB_OFT_ADDR_LIMIT - sdaddr);
+- else
+- dsize = size;
+-
+- /* Set the backplane window to include the start address */
+- bcmerror = dhdsdio_set_siaddr_window(bus, address);
+- if (bcmerror) {
+- DHD_ERROR(("%s: window change failed\n", __func__));
+- goto xfer_done;
+- }
+-
+- /* Do the transfer(s) */
+- while (size) {
+- DHD_INFO(("%s: %s %d bytes at offset 0x%08x in window 0x%08x\n",
+- __func__, (write ? "write" : "read"), dsize,
+- sdaddr, (address & SBSDIO_SBWINDOW_MASK)));
+- bcmerror =
+- bcmsdh_rwdata(bus->sdh, write, sdaddr, data, dsize);
+- if (bcmerror) {
+- DHD_ERROR(("%s: membytes transfer failed\n", __func__));
+- break;
+- }
+-
+- /* Adjust for next transfer (if any) */
+- size -= dsize;
+- if (size) {
+- data += dsize;
+- address += dsize;
+- bcmerror = dhdsdio_set_siaddr_window(bus, address);
+- if (bcmerror) {
+- DHD_ERROR(("%s: window change failed\n",
+- __func__));
+- break;
+- }
+- sdaddr = 0;
+- dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size);
+- }
+- }
+-
+-xfer_done:
+- /* Return the window to backplane enumeration space for core access */
+- if (dhdsdio_set_siaddr_window(bus, bcmsdh_cur_sbwad(bus->sdh))) {
+- DHD_ERROR(("%s: FAILED to set window back to 0x%x\n",
+- __func__, bcmsdh_cur_sbwad(bus->sdh)));
+- }
+-
+- return bcmerror;
+-}
+-
+-#ifdef DHD_DEBUG
+-static int dhdsdio_readshared(dhd_bus_t *bus, sdpcm_shared_t *sh)
+-{
+- u32 addr;
+- int rv;
+-
+- /* Read last word in memory to determine address of
+- sdpcm_shared structure */
+- rv = dhdsdio_membytes(bus, false, bus->ramsize - 4, (u8 *)&addr, 4);
+- if (rv < 0)
+- return rv;
+-
+- addr = le32_to_cpu(addr);
+-
+- DHD_INFO(("sdpcm_shared address 0x%08X\n", addr));
+-
+- /*
+- * Check if addr is valid.
+- * NVRAM length at the end of memory should have been overwritten.
+- */
+- if (addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff)) {
+- DHD_ERROR(("%s: address (0x%08x) of sdpcm_shared invalid\n",
+- __func__, addr));
+- return -EBADE;
+- }
+-
+- /* Read hndrte_shared structure */
+- rv = dhdsdio_membytes(bus, false, addr, (u8 *) sh,
+- sizeof(sdpcm_shared_t));
+- if (rv < 0)
+- return rv;
+-
+- /* Endianness */
+- sh->flags = le32_to_cpu(sh->flags);
+- sh->trap_addr = le32_to_cpu(sh->trap_addr);
+- sh->assert_exp_addr = le32_to_cpu(sh->assert_exp_addr);
+- sh->assert_file_addr = le32_to_cpu(sh->assert_file_addr);
+- sh->assert_line = le32_to_cpu(sh->assert_line);
+- sh->console_addr = le32_to_cpu(sh->console_addr);
+- sh->msgtrace_addr = le32_to_cpu(sh->msgtrace_addr);
+-
+- if ((sh->flags & SDPCM_SHARED_VERSION_MASK) != SDPCM_SHARED_VERSION) {
+- DHD_ERROR(("%s: sdpcm_shared version %d in dhd "
+- "is different than sdpcm_shared version %d in dongle\n",
+- __func__, SDPCM_SHARED_VERSION,
+- sh->flags & SDPCM_SHARED_VERSION_MASK));
+- return -EBADE;
+- }
+-
+- return 0;
+-}
+-
+-static int dhdsdio_checkdied(dhd_bus_t *bus, u8 *data, uint size)
+-{
+- int bcmerror = 0;
+- uint msize = 512;
+- char *mbuffer = NULL;
+- uint maxstrlen = 256;
+- char *str = NULL;
+- trap_t tr;
+- sdpcm_shared_t sdpcm_shared;
+- struct bcmstrbuf strbuf;
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- if (data == NULL) {
+- /*
+- * Called after a rx ctrl timeout. "data" is NULL.
+- * allocate memory to trace the trap or assert.
+- */
+- size = msize;
+- mbuffer = data = kmalloc(msize, GFP_ATOMIC);
+- if (mbuffer == NULL) {
+- DHD_ERROR(("%s: kmalloc(%d) failed\n", __func__,
+- msize));
+- bcmerror = -ENOMEM;
+- goto done;
+- }
+- }
+-
+- str = kmalloc(maxstrlen, GFP_ATOMIC);
+- if (str == NULL) {
+- DHD_ERROR(("%s: kmalloc(%d) failed\n", __func__, maxstrlen));
+- bcmerror = -ENOMEM;
+- goto done;
+- }
+-
+- bcmerror = dhdsdio_readshared(bus, &sdpcm_shared);
+- if (bcmerror < 0)
+- goto done;
+-
+- bcm_binit(&strbuf, data, size);
+-
+- bcm_bprintf(&strbuf,
+- "msgtrace address : 0x%08X\nconsole address : 0x%08X\n",
+- sdpcm_shared.msgtrace_addr, sdpcm_shared.console_addr);
+-
+- if ((sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT) == 0) {
+- /* NOTE: Misspelled assert is intentional - DO NOT FIX.
+- * (Avoids conflict with real asserts for programmatic
+- * parsing of output.)
+- */
+- bcm_bprintf(&strbuf, "Assrt not built in dongle\n");
+- }
+-
+- if ((sdpcm_shared.flags & (SDPCM_SHARED_ASSERT | SDPCM_SHARED_TRAP)) ==
+- 0) {
+- /* NOTE: Misspelled assert is intentional - DO NOT FIX.
+- * (Avoids conflict with real asserts for programmatic
+- * parsing of output.)
+- */
+- bcm_bprintf(&strbuf, "No trap%s in dongle",
+- (sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT)
+- ? "/assrt" : "");
+- } else {
+- if (sdpcm_shared.flags & SDPCM_SHARED_ASSERT) {
+- /* Download assert */
+- bcm_bprintf(&strbuf, "Dongle assert");
+- if (sdpcm_shared.assert_exp_addr != 0) {
+- str[0] = '\0';
+- bcmerror = dhdsdio_membytes(bus, false,
+- sdpcm_shared.assert_exp_addr,
+- (u8 *) str, maxstrlen);
+- if (bcmerror < 0)
+- goto done;
+-
+- str[maxstrlen - 1] = '\0';
+- bcm_bprintf(&strbuf, " expr \"%s\"", str);
+- }
+-
+- if (sdpcm_shared.assert_file_addr != 0) {
+- str[0] = '\0';
+- bcmerror = dhdsdio_membytes(bus, false,
+- sdpcm_shared.assert_file_addr,
+- (u8 *) str, maxstrlen);
+- if (bcmerror < 0)
+- goto done;
+-
+- str[maxstrlen - 1] = '\0';
+- bcm_bprintf(&strbuf, " file \"%s\"", str);
+- }
+-
+- bcm_bprintf(&strbuf, " line %d ",
+- sdpcm_shared.assert_line);
+- }
+-
+- if (sdpcm_shared.flags & SDPCM_SHARED_TRAP) {
+- bcmerror = dhdsdio_membytes(bus, false,
+- sdpcm_shared.trap_addr, (u8 *)&tr,
+- sizeof(trap_t));
+- if (bcmerror < 0)
+- goto done;
+-
+- bcm_bprintf(&strbuf,
+- "Dongle trap type 0x%x @ epc 0x%x, cpsr 0x%x, spsr 0x%x, sp 0x%x,"
+- "lp 0x%x, rpc 0x%x Trap offset 0x%x, "
+- "r0 0x%x, r1 0x%x, r2 0x%x, r3 0x%x, r4 0x%x, r5 0x%x, r6 0x%x, r7 0x%x\n",
+- tr.type, tr.epc, tr.cpsr, tr.spsr, tr.r13,
+- tr.r14, tr.pc, sdpcm_shared.trap_addr,
+- tr.r0, tr.r1, tr.r2, tr.r3, tr.r4, tr.r5,
+- tr.r6, tr.r7);
+- }
+- }
+-
+- if (sdpcm_shared.flags & (SDPCM_SHARED_ASSERT | SDPCM_SHARED_TRAP))
+- DHD_ERROR(("%s: %s\n", __func__, strbuf.origbuf));
+-
+-#ifdef DHD_DEBUG
+- if (sdpcm_shared.flags & SDPCM_SHARED_TRAP) {
+- /* Mem dump to a file on device */
+- dhdsdio_mem_dump(bus);
+- }
+-#endif /* DHD_DEBUG */
+-
+-done:
+- kfree(mbuffer);
+- kfree(str);
+-
+- return bcmerror;
+-}
+-
+-static int dhdsdio_mem_dump(dhd_bus_t *bus)
+-{
+- int ret = 0;
+- int size; /* Full mem size */
+- int start = 0; /* Start address */
+- int read_size = 0; /* Read size of each iteration */
+- u8 *buf = NULL, *databuf = NULL;
+-
+- /* Get full mem size */
+- size = bus->ramsize;
+- buf = kmalloc(size, GFP_ATOMIC);
+- if (!buf) {
+- DHD_ERROR(("%s: Out of memory (%d bytes)\n", __func__, size));
+- return -1;
+- }
+-
+- /* Read mem content */
+- printk(KERN_DEBUG "Dump dongle memory");
+- databuf = buf;
+- while (size) {
+- read_size = min(MEMBLOCK, size);
+- ret = dhdsdio_membytes(bus, false, start, databuf, read_size);
+- if (ret) {
+- DHD_ERROR(("%s: Error membytes %d\n", __func__, ret));
+- kfree(buf);
+- return -1;
+- }
+- printk(".");
+-
+- /* Decrement size and increment start address */
+- size -= read_size;
+- start += read_size;
+- databuf += read_size;
+- }
+- printk(KERN_DEBUG "Done\n");
+-
+- /* free buf before return !!! */
+- if (write_to_file(bus->dhd, buf, bus->ramsize)) {
+- DHD_ERROR(("%s: Error writing to files\n", __func__));
+- return -1;
+- }
+-
+- /* buf free handled in write_to_file, not here */
+- return 0;
+-}
+-
+-#define CONSOLE_LINE_MAX 192
+-
+-static int dhdsdio_readconsole(dhd_bus_t *bus)
+-{
+- dhd_console_t *c = &bus->console;
+- u8 line[CONSOLE_LINE_MAX], ch;
+- u32 n, idx, addr;
+- int rv;
+-
+- /* Don't do anything until FWREADY updates console address */
+- if (bus->console_addr == 0)
+- return 0;
+-
+- /* Read console log struct */
+- addr = bus->console_addr + offsetof(hndrte_cons_t, log);
+- rv = dhdsdio_membytes(bus, false, addr, (u8 *)&c->log,
+- sizeof(c->log));
+- if (rv < 0)
+- return rv;
+-
+- /* Allocate console buffer (one time only) */
+- if (c->buf == NULL) {
+- c->bufsize = le32_to_cpu(c->log.buf_size);
+- c->buf = kmalloc(c->bufsize, GFP_ATOMIC);
+- if (c->buf == NULL)
+- return -ENOMEM;
+- }
+-
+- idx = le32_to_cpu(c->log.idx);
+-
+- /* Protect against corrupt value */
+- if (idx > c->bufsize)
+- return -EBADE;
+-
+- /* Skip reading the console buffer if the index pointer
+- has not moved */
+- if (idx == c->last)
+- return 0;
+-
+- /* Read the console buffer */
+- addr = le32_to_cpu(c->log.buf);
+- rv = dhdsdio_membytes(bus, false, addr, c->buf, c->bufsize);
+- if (rv < 0)
+- return rv;
+-
+- while (c->last != idx) {
+- for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) {
+- if (c->last == idx) {
+- /* This would output a partial line.
+- * Instead, back up
+- * the buffer pointer and output this
+- * line next time around.
+- */
+- if (c->last >= n)
+- c->last -= n;
+- else
+- c->last = c->bufsize - n;
+- goto break2;
+- }
+- ch = c->buf[c->last];
+- c->last = (c->last + 1) % c->bufsize;
+- if (ch == '\n')
+- break;
+- line[n] = ch;
+- }
+-
+- if (n > 0) {
+- if (line[n - 1] == '\r')
+- n--;
+- line[n] = 0;
+- printk(KERN_DEBUG "CONSOLE: %s\n", line);
+- }
+- }
+-break2:
+-
+- return 0;
+-}
+-#endif /* DHD_DEBUG */
+-
+-int dhdsdio_downloadvars(dhd_bus_t *bus, void *arg, int len)
+-{
+- int bcmerror = 0;
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- /* Basic sanity checks */
+- if (bus->dhd->up) {
+- bcmerror = -EISCONN;
+- goto err;
+- }
+- if (!len) {
+- bcmerror = -EOVERFLOW;
+- goto err;
+- }
+-
+- /* Free the old ones and replace with passed variables */
+- kfree(bus->vars);
+-
+- bus->vars = kmalloc(len, GFP_ATOMIC);
+- bus->varsz = bus->vars ? len : 0;
+- if (bus->vars == NULL) {
+- bcmerror = -ENOMEM;
+- goto err;
+- }
+-
+- /* Copy the passed variables, which should include the
+- terminating double-null */
+- memcpy(bus->vars, arg, bus->varsz);
+-err:
+- return bcmerror;
+-}
+-
+-static int
+-dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
+- const char *name, void *params, int plen, void *arg, int len,
+- int val_size)
+-{
+- int bcmerror = 0;
+- s32 int_val = 0;
+- bool bool_val = 0;
+-
+- DHD_TRACE(("%s: Enter, action %d name %s params %p plen %d arg %p "
+- "len %d val_size %d\n",
+- __func__, actionid, name, params, plen, arg, len, val_size));
+-
+- bcmerror = bcm_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid));
+- if (bcmerror != 0)
+- goto exit;
+-
+- if (plen >= (int)sizeof(int_val))
+- memcpy(&int_val, params, sizeof(int_val));
+-
+- bool_val = (int_val != 0) ? true : false;
+-
+- /* Some ioctls use the bus */
+- dhd_os_sdlock(bus->dhd);
+-
+- /* Check if dongle is in reset. If so, only allow DEVRESET iovars */
+- if (bus->dhd->dongle_reset && !(actionid == IOV_SVAL(IOV_DEVRESET) ||
+- actionid == IOV_GVAL(IOV_DEVRESET))) {
+- bcmerror = -EPERM;
+- goto exit;
+- }
+-
+- /* Handle sleep stuff before any clock mucking */
+- if (vi->varid == IOV_SLEEP) {
+- if (IOV_ISSET(actionid)) {
+- bcmerror = dhdsdio_bussleep(bus, bool_val);
+- } else {
+- int_val = (s32) bus->sleeping;
+- memcpy(arg, &int_val, val_size);
+- }
+- goto exit;
+- }
+-
+- /* Request clock to allow SDIO accesses */
+- if (!bus->dhd->dongle_reset) {
+- BUS_WAKE(bus);
+- dhdsdio_clkctl(bus, CLK_AVAIL, false);
+- }
+-
+- switch (actionid) {
+- case IOV_GVAL(IOV_INTR):
+- int_val = (s32) bus->intr;
+- memcpy(arg, &int_val, val_size);
+- break;
+-
+- case IOV_SVAL(IOV_INTR):
+- bus->intr = bool_val;
+- bus->intdis = false;
+- if (bus->dhd->up) {
+- if (bus->intr) {
+- DHD_INTR(("%s: enable SDIO device interrupts\n",
+- __func__));
+- bcmsdh_intr_enable(bus->sdh);
+- } else {
+- DHD_INTR(("%s: disable SDIO interrupts\n",
+- __func__));
+- bcmsdh_intr_disable(bus->sdh);
+- }
+- }
+- break;
+-
+- case IOV_GVAL(IOV_POLLRATE):
+- int_val = (s32) bus->pollrate;
+- memcpy(arg, &int_val, val_size);
+- break;
+-
+- case IOV_SVAL(IOV_POLLRATE):
+- bus->pollrate = (uint) int_val;
+- bus->poll = (bus->pollrate != 0);
+- break;
+-
+- case IOV_GVAL(IOV_IDLETIME):
+- int_val = bus->idletime;
+- memcpy(arg, &int_val, val_size);
+- break;
+-
+- case IOV_SVAL(IOV_IDLETIME):
+- if ((int_val < 0) && (int_val != DHD_IDLE_IMMEDIATE))
+- bcmerror = -EINVAL;
+- else
+- bus->idletime = int_val;
+- break;
+-
+- case IOV_GVAL(IOV_IDLECLOCK):
+- int_val = (s32) bus->idleclock;
+- memcpy(arg, &int_val, val_size);
+- break;
+-
+- case IOV_SVAL(IOV_IDLECLOCK):
+- bus->idleclock = int_val;
+- break;
+-
+- case IOV_GVAL(IOV_SD1IDLE):
+- int_val = (s32) sd1idle;
+- memcpy(arg, &int_val, val_size);
+- break;
+-
+- case IOV_SVAL(IOV_SD1IDLE):
+- sd1idle = bool_val;
+- break;
+-
+- case IOV_SVAL(IOV_MEMBYTES):
+- case IOV_GVAL(IOV_MEMBYTES):
+- {
+- u32 address;
+- uint size, dsize;
+- u8 *data;
+-
+- bool set = (actionid == IOV_SVAL(IOV_MEMBYTES));
+-
+- ASSERT(plen >= 2 * sizeof(int));
+-
+- address = (u32) int_val;
+- memcpy(&int_val, (char *)params + sizeof(int_val),
+- sizeof(int_val));
+- size = (uint) int_val;
+-
+- /* Do some validation */
+- dsize = set ? plen - (2 * sizeof(int)) : len;
+- if (dsize < size) {
+- DHD_ERROR(("%s: error on %s membytes, addr "
+- "0x%08x size %d dsize %d\n",
+- __func__, (set ? "set" : "get"),
+- address, size, dsize));
+- bcmerror = -EINVAL;
+- break;
+- }
+-
+- DHD_INFO(("%s: Request to %s %d bytes at address "
+- "0x%08x\n",
+- __func__, (set ? "write" : "read"), size, address));
+-
+- /* If we know about SOCRAM, check for a fit */
+- if ((bus->orig_ramsize) &&
+- ((address > bus->orig_ramsize)
+- || (address + size > bus->orig_ramsize))) {
+- DHD_ERROR(("%s: ramsize 0x%08x doesn't have %d "
+- "bytes at 0x%08x\n",
+- __func__, bus->orig_ramsize, size, address));
+- bcmerror = -EINVAL;
+- break;
+- }
+-
+- /* Generate the actual data pointer */
+- data =
+- set ? (u8 *) params +
+- 2 * sizeof(int) : (u8 *) arg;
+-
+- /* Call to do the transfer */
+- bcmerror =
+- dhdsdio_membytes(bus, set, address, data, size);
+-
+- break;
+- }
+-
+- case IOV_GVAL(IOV_MEMSIZE):
+- int_val = (s32) bus->ramsize;
+- memcpy(arg, &int_val, val_size);
+- break;
+-
+- case IOV_GVAL(IOV_SDIOD_DRIVE):
+- int_val = (s32) dhd_sdiod_drive_strength;
+- memcpy(arg, &int_val, val_size);
+- break;
+-
+- case IOV_SVAL(IOV_SDIOD_DRIVE):
+- dhd_sdiod_drive_strength = int_val;
+- dhdsdio_sdiod_drive_strength_init(bus,
+- dhd_sdiod_drive_strength);
+- break;
+-
+- case IOV_SVAL(IOV_DOWNLOAD):
+- bcmerror = dhdsdio_download_state(bus, bool_val);
+- break;
+-
+- case IOV_SVAL(IOV_VARS):
+- bcmerror = dhdsdio_downloadvars(bus, arg, len);
+- break;
+-
+- case IOV_GVAL(IOV_READAHEAD):
+- int_val = (s32) dhd_readahead;
+- memcpy(arg, &int_val, val_size);
+- break;
+-
+- case IOV_SVAL(IOV_READAHEAD):
+- if (bool_val && !dhd_readahead)
+- bus->nextlen = 0;
+- dhd_readahead = bool_val;
+- break;
+-
+- case IOV_GVAL(IOV_SDRXCHAIN):
+- int_val = (s32) bus->use_rxchain;
+- memcpy(arg, &int_val, val_size);
+- break;
+-
+- case IOV_SVAL(IOV_SDRXCHAIN):
+- if (bool_val && !bus->sd_rxchain)
+- bcmerror = -ENOTSUPP;
+- else
+- bus->use_rxchain = bool_val;
+- break;
+- case IOV_GVAL(IOV_ALIGNCTL):
+- int_val = (s32) dhd_alignctl;
+- memcpy(arg, &int_val, val_size);
+- break;
+-
+- case IOV_SVAL(IOV_ALIGNCTL):
+- dhd_alignctl = bool_val;
+- break;
+-
+- case IOV_GVAL(IOV_SDALIGN):
+- int_val = DHD_SDALIGN;
+- memcpy(arg, &int_val, val_size);
+- break;
+-
+-#ifdef DHD_DEBUG
+- case IOV_GVAL(IOV_VARS):
+- if (bus->varsz < (uint) len)
+- memcpy(arg, bus->vars, bus->varsz);
+- else
+- bcmerror = -EOVERFLOW;
+- break;
+-#endif /* DHD_DEBUG */
+-
+-#ifdef DHD_DEBUG
+- case IOV_GVAL(IOV_SDREG):
+- {
+- sdreg_t *sd_ptr;
+- u32 addr, size;
+-
+- sd_ptr = (sdreg_t *) params;
+-
+- addr = (unsigned long)bus->regs + sd_ptr->offset;
+- size = sd_ptr->func;
+- int_val = (s32) bcmsdh_reg_read(bus->sdh, addr, size);
+- if (bcmsdh_regfail(bus->sdh))
+- bcmerror = -EIO;
+- memcpy(arg, &int_val, sizeof(s32));
+- break;
+- }
+-
+- case IOV_SVAL(IOV_SDREG):
+- {
+- sdreg_t *sd_ptr;
+- u32 addr, size;
+-
+- sd_ptr = (sdreg_t *) params;
+-
+- addr = (unsigned long)bus->regs + sd_ptr->offset;
+- size = sd_ptr->func;
+- bcmsdh_reg_write(bus->sdh, addr, size, sd_ptr->value);
+- if (bcmsdh_regfail(bus->sdh))
+- bcmerror = -EIO;
+- break;
+- }
+-
+- /* Same as above, but offset is not backplane
+- (not SDIO core) */
+- case IOV_GVAL(IOV_SBREG):
+- {
+- sdreg_t sdreg;
+- u32 addr, size;
+-
+- memcpy(&sdreg, params, sizeof(sdreg));
+-
+- addr = SI_ENUM_BASE + sdreg.offset;
+- size = sdreg.func;
+- int_val = (s32) bcmsdh_reg_read(bus->sdh, addr, size);
+- if (bcmsdh_regfail(bus->sdh))
+- bcmerror = -EIO;
+- memcpy(arg, &int_val, sizeof(s32));
+- break;
+- }
+-
+- case IOV_SVAL(IOV_SBREG):
+- {
+- sdreg_t sdreg;
+- u32 addr, size;
+-
+- memcpy(&sdreg, params, sizeof(sdreg));
+-
+- addr = SI_ENUM_BASE + sdreg.offset;
+- size = sdreg.func;
+- bcmsdh_reg_write(bus->sdh, addr, size, sdreg.value);
+- if (bcmsdh_regfail(bus->sdh))
+- bcmerror = -EIO;
+- break;
+- }
+-
+- case IOV_GVAL(IOV_SDCIS):
+- {
+- *(char *)arg = 0;
+-
+- strcat(arg, "\nFunc 0\n");
+- bcmsdh_cis_read(bus->sdh, 0x10,
+- (u8 *) arg + strlen(arg),
+- SBSDIO_CIS_SIZE_LIMIT);
+- strcat(arg, "\nFunc 1\n");
+- bcmsdh_cis_read(bus->sdh, 0x11,
+- (u8 *) arg + strlen(arg),
+- SBSDIO_CIS_SIZE_LIMIT);
+- strcat(arg, "\nFunc 2\n");
+- bcmsdh_cis_read(bus->sdh, 0x12,
+- (u8 *) arg + strlen(arg),
+- SBSDIO_CIS_SIZE_LIMIT);
+- break;
+- }
+-
+- case IOV_GVAL(IOV_FORCEEVEN):
+- int_val = (s32) forcealign;
+- memcpy(arg, &int_val, val_size);
+- break;
+-
+- case IOV_SVAL(IOV_FORCEEVEN):
+- forcealign = bool_val;
+- break;
+-
+- case IOV_GVAL(IOV_TXBOUND):
+- int_val = (s32) dhd_txbound;
+- memcpy(arg, &int_val, val_size);
+- break;
+-
+- case IOV_SVAL(IOV_TXBOUND):
+- dhd_txbound = (uint) int_val;
+- break;
+-
+- case IOV_GVAL(IOV_RXBOUND):
+- int_val = (s32) dhd_rxbound;
+- memcpy(arg, &int_val, val_size);
+- break;
+-
+- case IOV_SVAL(IOV_RXBOUND):
+- dhd_rxbound = (uint) int_val;
+- break;
+-
+- case IOV_GVAL(IOV_TXMINMAX):
+- int_val = (s32) dhd_txminmax;
+- memcpy(arg, &int_val, val_size);
+- break;
+-
+- case IOV_SVAL(IOV_TXMINMAX):
+- dhd_txminmax = (uint) int_val;
+- break;
+-#endif /* DHD_DEBUG */
+-
+-#ifdef SDTEST
+- case IOV_GVAL(IOV_EXTLOOP):
+- int_val = (s32) bus->ext_loop;
+- memcpy(arg, &int_val, val_size);
+- break;
+-
+- case IOV_SVAL(IOV_EXTLOOP):
+- bus->ext_loop = bool_val;
+- break;
+-
+- case IOV_GVAL(IOV_PKTGEN):
+- bcmerror = dhdsdio_pktgen_get(bus, arg);
+- break;
+-
+- case IOV_SVAL(IOV_PKTGEN):
+- bcmerror = dhdsdio_pktgen_set(bus, arg);
+- break;
+-#endif /* SDTEST */
+-
+- case IOV_SVAL(IOV_DEVRESET):
+- DHD_TRACE(("%s: Called set IOV_DEVRESET=%d dongle_reset=%d "
+- "busstate=%d\n",
+- __func__, bool_val, bus->dhd->dongle_reset,
+- bus->dhd->busstate));
+-
+- dhd_bus_devreset(bus->dhd, (u8) bool_val);
+-
+- break;
+-
+- case IOV_GVAL(IOV_DEVRESET):
+- DHD_TRACE(("%s: Called get IOV_DEVRESET\n", __func__));
+-
+- /* Get its status */
+- int_val = (bool) bus->dhd->dongle_reset;
+- memcpy(arg, &int_val, val_size);
+-
+- break;
+-
+- default:
+- bcmerror = -ENOTSUPP;
+- break;
+- }
+-
+-exit:
+- if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
+- bus->activity = false;
+- dhdsdio_clkctl(bus, CLK_NONE, true);
+- }
+-
+- dhd_os_sdunlock(bus->dhd);
+-
+- if (actionid == IOV_SVAL(IOV_DEVRESET) && bool_val == false)
+- dhd_preinit_ioctls((dhd_pub_t *) bus->dhd);
+-
+- return bcmerror;
+-}
+-
+-static int dhdsdio_write_vars(dhd_bus_t *bus)
+-{
+- int bcmerror = 0;
+- u32 varsize;
+- u32 varaddr;
+- u8 *vbuffer;
+- u32 varsizew;
+-#ifdef DHD_DEBUG
+- char *nvram_ularray;
+-#endif /* DHD_DEBUG */
+-
+- /* Even if there are no vars are to be written, we still
+- need to set the ramsize. */
+- varsize = bus->varsz ? roundup(bus->varsz, 4) : 0;
+- varaddr = (bus->ramsize - 4) - varsize;
+-
+- if (bus->vars) {
+- vbuffer = kzalloc(varsize, GFP_ATOMIC);
+- if (!vbuffer)
+- return -ENOMEM;
+-
+- memcpy(vbuffer, bus->vars, bus->varsz);
+-
+- /* Write the vars list */
+- bcmerror =
+- dhdsdio_membytes(bus, true, varaddr, vbuffer, varsize);
+-#ifdef DHD_DEBUG
+- /* Verify NVRAM bytes */
+- DHD_INFO(("Compare NVRAM dl & ul; varsize=%d\n", varsize));
+- nvram_ularray = kmalloc(varsize, GFP_ATOMIC);
+- if (!nvram_ularray)
+- return -ENOMEM;
+-
+- /* Upload image to verify downloaded contents. */
+- memset(nvram_ularray, 0xaa, varsize);
+-
+- /* Read the vars list to temp buffer for comparison */
+- bcmerror =
+- dhdsdio_membytes(bus, false, varaddr, nvram_ularray,
+- varsize);
+- if (bcmerror) {
+- DHD_ERROR(("%s: error %d on reading %d nvram bytes at "
+- "0x%08x\n", __func__, bcmerror, varsize, varaddr));
+- }
+- /* Compare the org NVRAM with the one read from RAM */
+- if (memcmp(vbuffer, nvram_ularray, varsize)) {
+- DHD_ERROR(("%s: Downloaded NVRAM image is corrupted.\n",
+- __func__));
+- } else
+- DHD_ERROR(("%s: Download/Upload/Compare of NVRAM ok.\n",
+- __func__));
+-
+- kfree(nvram_ularray);
+-#endif /* DHD_DEBUG */
+-
+- kfree(vbuffer);
+- }
+-
+- /* adjust to the user specified RAM */
+- DHD_INFO(("Physical memory size: %d, usable memory size: %d\n",
+- bus->orig_ramsize, bus->ramsize));
+- DHD_INFO(("Vars are at %d, orig varsize is %d\n", varaddr, varsize));
+- varsize = ((bus->orig_ramsize - 4) - varaddr);
+-
+- /*
+- * Determine the length token:
+- * Varsize, converted to words, in lower 16-bits, checksum
+- * in upper 16-bits.
+- */
+- if (bcmerror) {
+- varsizew = 0;
+- } else {
+- varsizew = varsize / 4;
+- varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF);
+- varsizew = cpu_to_le32(varsizew);
+- }
+-
+- DHD_INFO(("New varsize is %d, length token=0x%08x\n", varsize,
+- varsizew));
+-
+- /* Write the length token to the last word */
+- bcmerror = dhdsdio_membytes(bus, true, (bus->orig_ramsize - 4),
+- (u8 *)&varsizew, 4);
+-
+- return bcmerror;
+-}
+-
+-static int dhdsdio_download_state(dhd_bus_t *bus, bool enter)
+-{
+- uint retries;
+- u32 regdata;
+- int bcmerror = 0;
+-
+- /* To enter download state, disable ARM and reset SOCRAM.
+- * To exit download state, simply reset ARM (default is RAM boot).
+- */
+- if (enter) {
+- bus->alp_only = true;
+-
+- dhdsdio_chip_disablecore(bus->sdh, bus->ci->armcorebase);
+-
+- dhdsdio_chip_resetcore(bus->sdh, bus->ci->ramcorebase);
+-
+- /* Clear the top bit of memory */
+- if (bus->ramsize) {
+- u32 zeros = 0;
+- dhdsdio_membytes(bus, true, bus->ramsize - 4,
+- (u8 *)&zeros, 4);
+- }
+- } else {
+- regdata = bcmsdh_reg_read(bus->sdh,
+- CORE_SB(bus->ci->ramcorebase, sbtmstatelow), 4);
+- regdata &= (SBTML_RESET | SBTML_REJ_MASK |
+- (SICF_CLOCK_EN << SBTML_SICF_SHIFT));
+- if ((SICF_CLOCK_EN << SBTML_SICF_SHIFT) != regdata) {
+- DHD_ERROR(("%s: SOCRAM core is down after reset?\n",
+- __func__));
+- bcmerror = -EBADE;
+- goto fail;
+- }
+-
+- bcmerror = dhdsdio_write_vars(bus);
+- if (bcmerror) {
+- DHD_ERROR(("%s: no vars written to RAM\n", __func__));
+- bcmerror = 0;
+- }
+-
+- W_SDREG(0xFFFFFFFF, &bus->regs->intstatus, retries);
+-
+- dhdsdio_chip_resetcore(bus->sdh, bus->ci->armcorebase);
+-
+- /* Allow HT Clock now that the ARM is running. */
+- bus->alp_only = false;
+-
+- bus->dhd->busstate = DHD_BUS_LOAD;
+- }
+-fail:
+- return bcmerror;
+-}
+-
+-int
+-dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name,
+- void *params, int plen, void *arg, int len, bool set)
+-{
+- dhd_bus_t *bus = dhdp->bus;
+- const bcm_iovar_t *vi = NULL;
+- int bcmerror = 0;
+- int val_size;
+- u32 actionid;
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- ASSERT(name);
+- ASSERT(len >= 0);
+-
+- /* Get MUST have return space */
+- ASSERT(set || (arg && len));
+-
+- /* Set does NOT take qualifiers */
+- ASSERT(!set || (!params && !plen));
+-
+- /* Look up var locally; if not found pass to host driver */
+- vi = bcm_iovar_lookup(dhdsdio_iovars, name);
+- if (vi == NULL) {
+- dhd_os_sdlock(bus->dhd);
+-
+- BUS_WAKE(bus);
+-
+- /* Turn on clock in case SD command needs backplane */
+- dhdsdio_clkctl(bus, CLK_AVAIL, false);
+-
+- bcmerror =
+- bcmsdh_iovar_op(bus->sdh, name, params, plen, arg, len,
+- set);
+-
+- /* Check for bus configuration changes of interest */
+-
+- /* If it was divisor change, read the new one */
+- if (set && strcmp(name, "sd_divisor") == 0) {
+- if (bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0,
+- &bus->sd_divisor, sizeof(s32),
+- false) != 0) {
+- bus->sd_divisor = -1;
+- DHD_ERROR(("%s: fail on %s get\n", __func__,
+- name));
+- } else {
+- DHD_INFO(("%s: noted %s update, value now %d\n",
+- __func__, name, bus->sd_divisor));
+- }
+- }
+- /* If it was a mode change, read the new one */
+- if (set && strcmp(name, "sd_mode") == 0) {
+- if (bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0,
+- &bus->sd_mode, sizeof(s32),
+- false) != 0) {
+- bus->sd_mode = -1;
+- DHD_ERROR(("%s: fail on %s get\n", __func__,
+- name));
+- } else {
+- DHD_INFO(("%s: noted %s update, value now %d\n",
+- __func__, name, bus->sd_mode));
+- }
+- }
+- /* Similar check for blocksize change */
+- if (set && strcmp(name, "sd_blocksize") == 0) {
+- s32 fnum = 2;
+- if (bcmsdh_iovar_op
+- (bus->sdh, "sd_blocksize", &fnum, sizeof(s32),
+- &bus->blocksize, sizeof(s32),
+- false) != 0) {
+- bus->blocksize = 0;
+- DHD_ERROR(("%s: fail on %s get\n", __func__,
+- "sd_blocksize"));
+- } else {
+- DHD_INFO(("%s: noted %s update, value now %d\n",
+- __func__, "sd_blocksize",
+- bus->blocksize));
+- }
+- }
+- bus->roundup = min(max_roundup, bus->blocksize);
+-
+- if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
+- bus->activity = false;
+- dhdsdio_clkctl(bus, CLK_NONE, true);
+- }
+-
+- dhd_os_sdunlock(bus->dhd);
+- goto exit;
+- }
+-
+- DHD_CTL(("%s: %s %s, len %d plen %d\n", __func__,
+- name, (set ? "set" : "get"), len, plen));
+-
+- /* set up 'params' pointer in case this is a set command so that
+- * the convenience int and bool code can be common to set and get
+- */
+- if (params == NULL) {
+- params = arg;
+- plen = len;
+- }
+-
+- if (vi->type == IOVT_VOID)
+- val_size = 0;
+- else if (vi->type == IOVT_BUFFER)
+- val_size = len;
+- else
+- /* all other types are integer sized */
+- val_size = sizeof(int);
+-
+- actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
+- bcmerror =
+- dhdsdio_doiovar(bus, vi, actionid, name, params, plen, arg, len,
+- val_size);
+-
+-exit:
+- return bcmerror;
+-}
+-
+-void dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex)
+-{
+- u32 local_hostintmask;
+- u8 saveclk;
+- uint retries;
+- int err;
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- if (enforce_mutex)
+- dhd_os_sdlock(bus->dhd);
+-
+- BUS_WAKE(bus);
+-
+- /* Enable clock for device interrupts */
+- dhdsdio_clkctl(bus, CLK_AVAIL, false);
+-
+- /* Disable and clear interrupts at the chip level also */
+- W_SDREG(0, &bus->regs->hostintmask, retries);
+- local_hostintmask = bus->hostintmask;
+- bus->hostintmask = 0;
+-
+- /* Change our idea of bus state */
+- bus->dhd->busstate = DHD_BUS_DOWN;
+-
+- /* Force clocks on backplane to be sure F2 interrupt propagates */
+- saveclk =
+- bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
+- &err);
+- if (!err) {
+- bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
+- (saveclk | SBSDIO_FORCE_HT), &err);
+- }
+- if (err) {
+- DHD_ERROR(("%s: Failed to force clock for F2: err %d\n",
+- __func__, err));
+- }
+-
+- /* Turn off the bus (F2), free any pending packets */
+- DHD_INTR(("%s: disable SDIO interrupts\n", __func__));
+- bcmsdh_intr_disable(bus->sdh);
+- bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN,
+- SDIO_FUNC_ENABLE_1, NULL);
+-
+- /* Clear any pending interrupts now that F2 is disabled */
+- W_SDREG(local_hostintmask, &bus->regs->intstatus, retries);
+-
+- /* Turn off the backplane clock (only) */
+- dhdsdio_clkctl(bus, CLK_SDONLY, false);
+-
+- /* Clear the data packet queues */
+- bcm_pktq_flush(&bus->txq, true, NULL, NULL);
+-
+- /* Clear any held glomming stuff */
+- if (bus->glomd)
+- bcm_pkt_buf_free_skb(bus->glomd);
+-
+- if (bus->glom)
+- bcm_pkt_buf_free_skb(bus->glom);
+-
+- bus->glom = bus->glomd = NULL;
+-
+- /* Clear rx control and wake any waiters */
+- bus->rxlen = 0;
+- dhd_os_ioctl_resp_wake(bus->dhd);
+-
+- /* Reset some F2 state stuff */
+- bus->rxskip = false;
+- bus->tx_seq = bus->rx_seq = 0;
+-
+- if (enforce_mutex)
+- dhd_os_sdunlock(bus->dhd);
+-}
+-
+-int dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex)
+-{
+- dhd_bus_t *bus = dhdp->bus;
+- dhd_timeout_t tmo;
+- uint retries = 0;
+- u8 ready, enable;
+- int err, ret = 0;
+- u8 saveclk;
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- ASSERT(bus->dhd);
+- if (!bus->dhd)
+- return 0;
+-
+- if (enforce_mutex)
+- dhd_os_sdlock(bus->dhd);
+-
+- /* Make sure backplane clock is on, needed to generate F2 interrupt */
+- dhdsdio_clkctl(bus, CLK_AVAIL, false);
+- if (bus->clkstate != CLK_AVAIL)
+- goto exit;
+-
+- /* Force clocks on backplane to be sure F2 interrupt propagates */
+- saveclk =
+- bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
+- &err);
+- if (!err) {
+- bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
+- (saveclk | SBSDIO_FORCE_HT), &err);
+- }
+- if (err) {
+- DHD_ERROR(("%s: Failed to force clock for F2: err %d\n",
+- __func__, err));
+- goto exit;
+- }
+-
+- /* Enable function 2 (frame transfers) */
+- W_SDREG((SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT),
+- &bus->regs->tosbmailboxdata, retries);
+- enable = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2);
+-
+- bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, enable, NULL);
+-
+- /* Give the dongle some time to do its thing and set IOR2 */
+- dhd_timeout_start(&tmo, DHD_WAIT_F2RDY * 1000);
+-
+- ready = 0;
+- while (ready != enable && !dhd_timeout_expired(&tmo))
+- ready =
+- bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IORDY,
+- NULL);
+-
+- DHD_INFO(("%s: enable 0x%02x, ready 0x%02x (waited %uus)\n",
+- __func__, enable, ready, tmo.elapsed));
+-
+- /* If F2 successfully enabled, set core and enable interrupts */
+- if (ready == enable) {
+- /* Set up the interrupt mask and enable interrupts */
+- bus->hostintmask = HOSTINTMASK;
+- W_SDREG(bus->hostintmask,
+- (unsigned int *)CORE_BUS_REG(bus->ci->buscorebase,
+- hostintmask), retries);
+-
+- bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK,
+- (u8) watermark, &err);
+-
+- /* Set bus state according to enable result */
+- dhdp->busstate = DHD_BUS_DATA;
+-
+- /* bcmsdh_intr_unmask(bus->sdh); */
+-
+- bus->intdis = false;
+- if (bus->intr) {
+- DHD_INTR(("%s: enable SDIO device interrupts\n",
+- __func__));
+- bcmsdh_intr_enable(bus->sdh);
+- } else {
+- DHD_INTR(("%s: disable SDIO interrupts\n", __func__));
+- bcmsdh_intr_disable(bus->sdh);
+- }
+-
+- }
+-
+- else {
+- /* Disable F2 again */
+- enable = SDIO_FUNC_ENABLE_1;
+- bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, enable,
+- NULL);
+- }
+-
+- /* Restore previous clock setting */
+- bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
+- saveclk, &err);
+-
+- /* If we didn't come up, turn off backplane clock */
+- if (dhdp->busstate != DHD_BUS_DATA)
+- dhdsdio_clkctl(bus, CLK_NONE, false);
+-
+-exit:
+- if (enforce_mutex)
+- dhd_os_sdunlock(bus->dhd);
+-
+- return ret;
+-}
+-
+-static void dhdsdio_rxfail(dhd_bus_t *bus, bool abort, bool rtx)
+-{
+- bcmsdh_info_t *sdh = bus->sdh;
+- sdpcmd_regs_t *regs = bus->regs;
+- uint retries = 0;
+- u16 lastrbc;
+- u8 hi, lo;
+- int err;
+-
+- DHD_ERROR(("%s: %sterminate frame%s\n", __func__,
+- (abort ? "abort command, " : ""),
+- (rtx ? ", send NAK" : "")));
+-
+- if (abort)
+- bcmsdh_abort(sdh, SDIO_FUNC_2);
+-
+- bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL, SFC_RF_TERM,
+- &err);
+- bus->f1regdata++;
+-
+- /* Wait until the packet has been flushed (device/FIFO stable) */
+- for (lastrbc = retries = 0xffff; retries > 0; retries--) {
+- hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCHI,
+- NULL);
+- lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCLO,
+- NULL);
+- bus->f1regdata += 2;
+-
+- if ((hi == 0) && (lo == 0))
+- break;
+-
+- if ((hi > (lastrbc >> 8)) && (lo > (lastrbc & 0x00ff))) {
+- DHD_ERROR(("%s: count growing: last 0x%04x now "
+- "0x%04x\n",
+- __func__, lastrbc, ((hi << 8) + lo)));
+- }
+- lastrbc = (hi << 8) + lo;
+- }
+-
+- if (!retries) {
+- DHD_ERROR(("%s: count never zeroed: last 0x%04x\n",
+- __func__, lastrbc));
+- } else {
+- DHD_INFO(("%s: flush took %d iterations\n", __func__,
+- (0xffff - retries)));
+- }
+-
+- if (rtx) {
+- bus->rxrtx++;
+- W_SDREG(SMB_NAK, ®s->tosbmailbox, retries);
+- bus->f1regdata++;
+- if (retries <= retry_limit)
+- bus->rxskip = true;
+- }
+-
+- /* Clear partial in any case */
+- bus->nextlen = 0;
+-
+- /* If we can't reach the device, signal failure */
+- if (err || bcmsdh_regfail(sdh))
+- bus->dhd->busstate = DHD_BUS_DOWN;
+-}
+-
+-static void
+-dhdsdio_read_control(dhd_bus_t *bus, u8 *hdr, uint len, uint doff)
+-{
+- bcmsdh_info_t *sdh = bus->sdh;
+- uint rdlen, pad;
+-
+- int sdret;
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- /* Control data already received in aligned rxctl */
+- if ((bus->bus == SPI_BUS) && (!bus->usebufpool))
+- goto gotpkt;
+-
+- ASSERT(bus->rxbuf);
+- /* Set rxctl for frame (w/optional alignment) */
+- bus->rxctl = bus->rxbuf;
+- if (dhd_alignctl) {
+- bus->rxctl += firstread;
+- pad = ((unsigned long)bus->rxctl % DHD_SDALIGN);
+- if (pad)
+- bus->rxctl += (DHD_SDALIGN - pad);
+- bus->rxctl -= firstread;
+- }
+- ASSERT(bus->rxctl >= bus->rxbuf);
+-
+- /* Copy the already-read portion over */
+- memcpy(bus->rxctl, hdr, firstread);
+- if (len <= firstread)
+- goto gotpkt;
+-
+- /* Copy the full data pkt in gSPI case and process ioctl. */
+- if (bus->bus == SPI_BUS) {
+- memcpy(bus->rxctl, hdr, len);
+- goto gotpkt;
+- }
+-
+- /* Raise rdlen to next SDIO block to avoid tail command */
+- rdlen = len - firstread;
+- if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) {
+- pad = bus->blocksize - (rdlen % bus->blocksize);
+- if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
+- ((len + pad) < bus->dhd->maxctl))
+- rdlen += pad;
+- } else if (rdlen % DHD_SDALIGN) {
+- rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN);
+- }
+-
+- /* Satisfy length-alignment requirements */
+- if (forcealign && (rdlen & (ALIGNMENT - 1)))
+- rdlen = roundup(rdlen, ALIGNMENT);
+-
+- /* Drop if the read is too big or it exceeds our maximum */
+- if ((rdlen + firstread) > bus->dhd->maxctl) {
+- DHD_ERROR(("%s: %d-byte control read exceeds %d-byte buffer\n",
+- __func__, rdlen, bus->dhd->maxctl));
+- bus->dhd->rx_errors++;
+- dhdsdio_rxfail(bus, false, false);
+- goto done;
+- }
+-
+- if ((len - doff) > bus->dhd->maxctl) {
+- DHD_ERROR(("%s: %d-byte ctl frame (%d-byte ctl data) exceeds "
+- "%d-byte limit\n",
+- __func__, len, (len - doff), bus->dhd->maxctl));
+- bus->dhd->rx_errors++;
+- bus->rx_toolong++;
+- dhdsdio_rxfail(bus, false, false);
+- goto done;
+- }
+-
+- /* Read remainder of frame body into the rxctl buffer */
+- sdret = bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2,
+- F2SYNC, (bus->rxctl + firstread), rdlen,
+- NULL, NULL, NULL);
+- bus->f2rxdata++;
+- ASSERT(sdret != -BCME_PENDING);
+-
+- /* Control frame failures need retransmission */
+- if (sdret < 0) {
+- DHD_ERROR(("%s: read %d control bytes failed: %d\n",
+- __func__, rdlen, sdret));
+- bus->rxc_errors++; /* dhd.rx_ctlerrs is higher level */
+- dhdsdio_rxfail(bus, true, true);
+- goto done;
+- }
+-
+-gotpkt:
+-
+-#ifdef DHD_DEBUG
+- if (DHD_BYTES_ON() && DHD_CTL_ON()) {
+- printk(KERN_DEBUG "RxCtrl:\n");
+- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, bus->rxctl, len);
+- }
+-#endif
+-
+- /* Point to valid data and indicate its length */
+- bus->rxctl += doff;
+- bus->rxlen = len - doff;
+-
+-done:
+- /* Awake any waiters */
+- dhd_os_ioctl_resp_wake(bus->dhd);
+-}
+-
+-static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
+-{
+- u16 dlen, totlen;
+- u8 *dptr, num = 0;
+-
+- u16 sublen, check;
+- struct sk_buff *pfirst, *plast, *pnext, *save_pfirst;
+-
+- int errcode;
+- u8 chan, seq, doff, sfdoff;
+- u8 txmax;
+-
+- int ifidx = 0;
+- bool usechain = bus->use_rxchain;
+-
+- /* If packets, issue read(s) and send up packet chain */
+- /* Return sequence numbers consumed? */
+-
+- DHD_TRACE(("dhdsdio_rxglom: start: glomd %p glom %p\n", bus->glomd,
+- bus->glom));
+-
+- /* If there's a descriptor, generate the packet chain */
+- if (bus->glomd) {
+- dhd_os_sdlock_rxq(bus->dhd);
+-
+- pfirst = plast = pnext = NULL;
+- dlen = (u16) (bus->glomd->len);
+- dptr = bus->glomd->data;
+- if (!dlen || (dlen & 1)) {
+- DHD_ERROR(("%s: bad glomd len(%d), ignore descriptor\n",
+- __func__, dlen));
+- dlen = 0;
+- }
+-
+- for (totlen = num = 0; dlen; num++) {
+- /* Get (and move past) next length */
+- sublen = get_unaligned_le16(dptr);
+- dlen -= sizeof(u16);
+- dptr += sizeof(u16);
+- if ((sublen < SDPCM_HDRLEN) ||
+- ((num == 0) && (sublen < (2 * SDPCM_HDRLEN)))) {
+- DHD_ERROR(("%s: descriptor len %d bad: %d\n",
+- __func__, num, sublen));
+- pnext = NULL;
+- break;
+- }
+- if (sublen % DHD_SDALIGN) {
+- DHD_ERROR(("%s: sublen %d not multiple of %d\n",
+- __func__, sublen, DHD_SDALIGN));
+- usechain = false;
+- }
+- totlen += sublen;
+-
+- /* For last frame, adjust read len so total
+- is a block multiple */
+- if (!dlen) {
+- sublen +=
+- (roundup(totlen, bus->blocksize) - totlen);
+- totlen = roundup(totlen, bus->blocksize);
+- }
+-
+- /* Allocate/chain packet for next subframe */
+- pnext = bcm_pkt_buf_get_skb(sublen + DHD_SDALIGN);
+- if (pnext == NULL) {
+- DHD_ERROR(("%s: bcm_pkt_buf_get_skb failed, "
+- "num %d len %d\n", __func__,
+- num, sublen));
+- break;
+- }
+- ASSERT(!(pnext->prev));
+- if (!pfirst) {
+- ASSERT(!plast);
+- pfirst = plast = pnext;
+- } else {
+- ASSERT(plast);
+- plast->next = pnext;
+- plast = pnext;
+- }
+-
+- /* Adhere to start alignment requirements */
+- PKTALIGN(pnext, sublen, DHD_SDALIGN);
+- }
+-
+- /* If all allocations succeeded, save packet chain
+- in bus structure */
+- if (pnext) {
+- DHD_GLOM(("%s: allocated %d-byte packet chain for %d "
+- "subframes\n", __func__, totlen, num));
+- if (DHD_GLOM_ON() && bus->nextlen) {
+- if (totlen != bus->nextlen) {
+- DHD_GLOM(("%s: glomdesc mismatch: nextlen %d glomdesc %d " "rxseq %d\n",
+- __func__, bus->nextlen,
+- totlen, rxseq));
+- }
+- }
+- bus->glom = pfirst;
+- pfirst = pnext = NULL;
+- } else {
+- if (pfirst)
+- bcm_pkt_buf_free_skb(pfirst);
+- bus->glom = NULL;
+- num = 0;
+- }
+-
+- /* Done with descriptor packet */
+- bcm_pkt_buf_free_skb(bus->glomd);
+- bus->glomd = NULL;
+- bus->nextlen = 0;
+-
+- dhd_os_sdunlock_rxq(bus->dhd);
+- }
+-
+- /* Ok -- either we just generated a packet chain,
+- or had one from before */
+- if (bus->glom) {
+- if (DHD_GLOM_ON()) {
+- DHD_GLOM(("%s: try superframe read, packet chain:\n",
+- __func__));
+- for (pnext = bus->glom; pnext; pnext = pnext->next) {
+- DHD_GLOM((" %p: %p len 0x%04x (%d)\n",
+- pnext, (u8 *) (pnext->data),
+- pnext->len, pnext->len));
+- }
+- }
+-
+- pfirst = bus->glom;
+- dlen = (u16) bcm_pkttotlen(pfirst);
+-
+- /* Do an SDIO read for the superframe. Configurable iovar to
+- * read directly into the chained packet, or allocate a large
+- * packet and and copy into the chain.
+- */
+- if (usechain) {
+- errcode = bcmsdh_recv_buf(bus,
+- bcmsdh_cur_sbwad(bus->sdh), SDIO_FUNC_2,
+- F2SYNC, (u8 *) pfirst->data, dlen,
+- pfirst, NULL, NULL);
+- } else if (bus->dataptr) {
+- errcode = bcmsdh_recv_buf(bus,
+- bcmsdh_cur_sbwad(bus->sdh), SDIO_FUNC_2,
+- F2SYNC, bus->dataptr, dlen,
+- NULL, NULL, NULL);
+- sublen = (u16) bcm_pktfrombuf(pfirst, 0, dlen,
+- bus->dataptr);
+- if (sublen != dlen) {
+- DHD_ERROR(("%s: FAILED TO COPY, dlen %d sublen %d\n",
+- __func__, dlen, sublen));
+- errcode = -1;
+- }
+- pnext = NULL;
+- } else {
+- DHD_ERROR(("COULDN'T ALLOC %d-BYTE GLOM, FORCE FAILURE\n",
+- dlen));
+- errcode = -1;
+- }
+- bus->f2rxdata++;
+- ASSERT(errcode != -BCME_PENDING);
+-
+- /* On failure, kill the superframe, allow a couple retries */
+- if (errcode < 0) {
+- DHD_ERROR(("%s: glom read of %d bytes failed: %d\n",
+- __func__, dlen, errcode));
+- bus->dhd->rx_errors++;
+-
+- if (bus->glomerr++ < 3) {
+- dhdsdio_rxfail(bus, true, true);
+- } else {
+- bus->glomerr = 0;
+- dhdsdio_rxfail(bus, true, false);
+- dhd_os_sdlock_rxq(bus->dhd);
+- bcm_pkt_buf_free_skb(bus->glom);
+- dhd_os_sdunlock_rxq(bus->dhd);
+- bus->rxglomfail++;
+- bus->glom = NULL;
+- }
+- return 0;
+- }
+-#ifdef DHD_DEBUG
+- if (DHD_GLOM_ON()) {
+- printk(KERN_DEBUG "SUPERFRAME:\n");
+- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
+- pfirst->data, min_t(int, pfirst->len, 48));
+- }
+-#endif
+-
+- /* Validate the superframe header */
+- dptr = (u8 *) (pfirst->data);
+- sublen = get_unaligned_le16(dptr);
+- check = get_unaligned_le16(dptr + sizeof(u16));
+-
+- chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
+- seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
+- bus->nextlen = dptr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
+- if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
+- DHD_INFO(("%s: nextlen too large (%d) seq %d\n",
+- __func__, bus->nextlen, seq));
+- bus->nextlen = 0;
+- }
+- doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
+- txmax = SDPCM_WINDOW_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
+-
+- errcode = 0;
+- if ((u16)~(sublen ^ check)) {
+- DHD_ERROR(("%s (superframe): HW hdr error: len/check "
+- "0x%04x/0x%04x\n", __func__, sublen, check));
+- errcode = -1;
+- } else if (roundup(sublen, bus->blocksize) != dlen) {
+- DHD_ERROR(("%s (superframe): len 0x%04x, rounded "
+- "0x%04x, expect 0x%04x\n",
+- __func__, sublen,
+- roundup(sublen, bus->blocksize), dlen));
+- errcode = -1;
+- } else if (SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]) !=
+- SDPCM_GLOM_CHANNEL) {
+- DHD_ERROR(("%s (superframe): bad channel %d\n",
+- __func__,
+- SDPCM_PACKET_CHANNEL(&dptr
+- [SDPCM_FRAMETAG_LEN])));
+- errcode = -1;
+- } else if (SDPCM_GLOMDESC(&dptr[SDPCM_FRAMETAG_LEN])) {
+- DHD_ERROR(("%s (superframe): got second descriptor?\n",
+- __func__));
+- errcode = -1;
+- } else if ((doff < SDPCM_HDRLEN) ||
+- (doff > (pfirst->len - SDPCM_HDRLEN))) {
+- DHD_ERROR(("%s (superframe): Bad data offset %d: HW %d "
+- "pkt %d min %d\n",
+- __func__, doff, sublen,
+- pfirst->len, SDPCM_HDRLEN));
+- errcode = -1;
+- }
+-
+- /* Check sequence number of superframe SW header */
+- if (rxseq != seq) {
+- DHD_INFO(("%s: (superframe) rx_seq %d, expected %d\n",
+- __func__, seq, rxseq));
+- bus->rx_badseq++;
+- rxseq = seq;
+- }
+-
+- /* Check window for sanity */
+- if ((u8) (txmax - bus->tx_seq) > 0x40) {
+- DHD_ERROR(("%s: unlikely tx max %d with tx_seq %d\n",
+- __func__, txmax, bus->tx_seq));
+- txmax = bus->tx_seq + 2;
+- }
+- bus->tx_max = txmax;
+-
+- /* Remove superframe header, remember offset */
+- skb_pull(pfirst, doff);
+- sfdoff = doff;
+-
+- /* Validate all the subframe headers */
+- for (num = 0, pnext = pfirst; pnext && !errcode;
+- num++, pnext = pnext->next) {
+- dptr = (u8 *) (pnext->data);
+- dlen = (u16) (pnext->len);
+- sublen = get_unaligned_le16(dptr);
+- check = get_unaligned_le16(dptr + sizeof(u16));
+- chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
+- doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
+-#ifdef DHD_DEBUG
+- if (DHD_GLOM_ON()) {
+- printk(KERN_DEBUG "subframe:\n");
+- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
+- dptr, 32);
+- }
+-#endif
+-
+- if ((u16)~(sublen ^ check)) {
+- DHD_ERROR(("%s (subframe %d): HW hdr error: "
+- "len/check 0x%04x/0x%04x\n",
+- __func__, num, sublen, check));
+- errcode = -1;
+- } else if ((sublen > dlen) || (sublen < SDPCM_HDRLEN)) {
+- DHD_ERROR(("%s (subframe %d): length mismatch: "
+- "len 0x%04x, expect 0x%04x\n",
+- __func__, num, sublen, dlen));
+- errcode = -1;
+- } else if ((chan != SDPCM_DATA_CHANNEL) &&
+- (chan != SDPCM_EVENT_CHANNEL)) {
+- DHD_ERROR(("%s (subframe %d): bad channel %d\n",
+- __func__, num, chan));
+- errcode = -1;
+- } else if ((doff < SDPCM_HDRLEN) || (doff > sublen)) {
+- DHD_ERROR(("%s (subframe %d): Bad data offset %d: HW %d min %d\n",
+- __func__, num, doff, sublen,
+- SDPCM_HDRLEN));
+- errcode = -1;
+- }
+- }
+-
+- if (errcode) {
+- /* Terminate frame on error, request
+- a couple retries */
+- if (bus->glomerr++ < 3) {
+- /* Restore superframe header space */
+- skb_push(pfirst, sfdoff);
+- dhdsdio_rxfail(bus, true, true);
+- } else {
+- bus->glomerr = 0;
+- dhdsdio_rxfail(bus, true, false);
+- dhd_os_sdlock_rxq(bus->dhd);
+- bcm_pkt_buf_free_skb(bus->glom);
+- dhd_os_sdunlock_rxq(bus->dhd);
+- bus->rxglomfail++;
+- bus->glom = NULL;
+- }
+- bus->nextlen = 0;
+- return 0;
+- }
+-
+- /* Basic SD framing looks ok - process each packet (header) */
+- save_pfirst = pfirst;
+- bus->glom = NULL;
+- plast = NULL;
+-
+- dhd_os_sdlock_rxq(bus->dhd);
+- for (num = 0; pfirst; rxseq++, pfirst = pnext) {
+- pnext = pfirst->next;
+- pfirst->next = NULL;
+-
+- dptr = (u8 *) (pfirst->data);
+- sublen = get_unaligned_le16(dptr);
+- chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
+- seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
+- doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
+-
+- DHD_GLOM(("%s: Get subframe %d, %p(%p/%d), sublen %d "
+- "chan %d seq %d\n",
+- __func__, num, pfirst, pfirst->data,
+- pfirst->len, sublen, chan, seq));
+-
+- ASSERT((chan == SDPCM_DATA_CHANNEL)
+- || (chan == SDPCM_EVENT_CHANNEL));
+-
+- if (rxseq != seq) {
+- DHD_GLOM(("%s: rx_seq %d, expected %d\n",
+- __func__, seq, rxseq));
+- bus->rx_badseq++;
+- rxseq = seq;
+- }
+-#ifdef DHD_DEBUG
+- if (DHD_BYTES_ON() && DHD_DATA_ON()) {
+- printk(KERN_DEBUG "Rx Subframe Data:\n");
+- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
+- dptr, dlen);
+- }
+-#endif
+-
+- __skb_trim(pfirst, sublen);
+- skb_pull(pfirst, doff);
+-
+- if (pfirst->len == 0) {
+- bcm_pkt_buf_free_skb(pfirst);
+- if (plast) {
+- plast->next = pnext;
+- } else {
+- ASSERT(save_pfirst == pfirst);
+- save_pfirst = pnext;
+- }
+- continue;
+- } else if (dhd_prot_hdrpull(bus->dhd, &ifidx, pfirst) !=
+- 0) {
+- DHD_ERROR(("%s: rx protocol error\n",
+- __func__));
+- bus->dhd->rx_errors++;
+- bcm_pkt_buf_free_skb(pfirst);
+- if (plast) {
+- plast->next = pnext;
+- } else {
+- ASSERT(save_pfirst == pfirst);
+- save_pfirst = pnext;
+- }
+- continue;
+- }
+-
+- /* this packet will go up, link back into
+- chain and count it */
+- pfirst->next = pnext;
+- plast = pfirst;
+- num++;
+-
+-#ifdef DHD_DEBUG
+- if (DHD_GLOM_ON()) {
+- DHD_GLOM(("%s subframe %d to stack, %p(%p/%d) "
+- "nxt/lnk %p/%p\n",
+- __func__, num, pfirst, pfirst->data,
+- pfirst->len, pfirst->next,
+- pfirst->prev));
+- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
+- pfirst->data,
+- min_t(int, pfirst->len, 32));
+- }
+-#endif /* DHD_DEBUG */
+- }
+- dhd_os_sdunlock_rxq(bus->dhd);
+- if (num) {
+- dhd_os_sdunlock(bus->dhd);
+- dhd_rx_frame(bus->dhd, ifidx, save_pfirst, num);
+- dhd_os_sdlock(bus->dhd);
+- }
+-
+- bus->rxglomframes++;
+- bus->rxglompkts += num;
+- }
+- return num;
+-}
+-
+-/* Return true if there may be more frames to read */
+-static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
+-{
+- bcmsdh_info_t *sdh = bus->sdh;
+-
+- u16 len, check; /* Extracted hardware header fields */
+- u8 chan, seq, doff; /* Extracted software header fields */
+- u8 fcbits; /* Extracted fcbits from software header */
+-
+- struct sk_buff *pkt; /* Packet for event or data frames */
+- u16 pad; /* Number of pad bytes to read */
+- u16 rdlen; /* Total number of bytes to read */
+- u8 rxseq; /* Next sequence number to expect */
+- uint rxleft = 0; /* Remaining number of frames allowed */
+- int sdret; /* Return code from bcmsdh calls */
+- u8 txmax; /* Maximum tx sequence offered */
+- bool len_consistent; /* Result of comparing readahead len and
+- len from hw-hdr */
+- u8 *rxbuf;
+- int ifidx = 0;
+- uint rxcount = 0; /* Total frames read */
+-
+-#if defined(DHD_DEBUG) || defined(SDTEST)
+- bool sdtest = false; /* To limit message spew from test mode */
+-#endif
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- ASSERT(maxframes);
+-
+-#ifdef SDTEST
+- /* Allow pktgen to override maxframes */
+- if (bus->pktgen_count && (bus->pktgen_mode == DHD_PKTGEN_RECV)) {
+- maxframes = bus->pktgen_count;
+- sdtest = true;
+- }
+-#endif
+-
+- /* Not finished unless we encounter no more frames indication */
+- *finished = false;
+-
+- for (rxseq = bus->rx_seq, rxleft = maxframes;
+- !bus->rxskip && rxleft && bus->dhd->busstate != DHD_BUS_DOWN;
+- rxseq++, rxleft--) {
+-
+- /* Handle glomming separately */
+- if (bus->glom || bus->glomd) {
+- u8 cnt;
+- DHD_GLOM(("%s: calling rxglom: glomd %p, glom %p\n",
+- __func__, bus->glomd, bus->glom));
+- cnt = dhdsdio_rxglom(bus, rxseq);
+- DHD_GLOM(("%s: rxglom returned %d\n", __func__, cnt));
+- rxseq += cnt - 1;
+- rxleft = (rxleft > cnt) ? (rxleft - cnt) : 1;
+- continue;
+- }
+-
+- /* Try doing single read if we can */
+- if (dhd_readahead && bus->nextlen) {
+- u16 nextlen = bus->nextlen;
+- bus->nextlen = 0;
+-
+- if (bus->bus == SPI_BUS) {
+- rdlen = len = nextlen;
+- } else {
+- rdlen = len = nextlen << 4;
+-
+- /* Pad read to blocksize for efficiency */
+- if (bus->roundup && bus->blocksize
+- && (rdlen > bus->blocksize)) {
+- pad =
+- bus->blocksize -
+- (rdlen % bus->blocksize);
+- if ((pad <= bus->roundup)
+- && (pad < bus->blocksize)
+- && ((rdlen + pad + firstread) <
+- MAX_RX_DATASZ))
+- rdlen += pad;
+- } else if (rdlen % DHD_SDALIGN) {
+- rdlen +=
+- DHD_SDALIGN - (rdlen % DHD_SDALIGN);
+- }
+- }
+-
+- /* We use bus->rxctl buffer in WinXP for initial
+- * control pkt receives.
+- * Later we use buffer-poll for data as well
+- * as control packets.
+- * This is required because dhd receives full
+- * frame in gSPI unlike SDIO.
+- * After the frame is received we have to
+- * distinguish whether it is data
+- * or non-data frame.
+- */
+- /* Allocate a packet buffer */
+- dhd_os_sdlock_rxq(bus->dhd);
+- pkt = bcm_pkt_buf_get_skb(rdlen + DHD_SDALIGN);
+- if (!pkt) {
+- if (bus->bus == SPI_BUS) {
+- bus->usebufpool = false;
+- bus->rxctl = bus->rxbuf;
+- if (dhd_alignctl) {
+- bus->rxctl += firstread;
+- pad = ((unsigned long)bus->rxctl %
+- DHD_SDALIGN);
+- if (pad)
+- bus->rxctl +=
+- (DHD_SDALIGN - pad);
+- bus->rxctl -= firstread;
+- }
+- ASSERT(bus->rxctl >= bus->rxbuf);
+- rxbuf = bus->rxctl;
+- /* Read the entire frame */
+- sdret = bcmsdh_recv_buf(bus,
+- bcmsdh_cur_sbwad(sdh),
+- SDIO_FUNC_2, F2SYNC,
+- rxbuf, rdlen,
+- NULL, NULL, NULL);
+- bus->f2rxdata++;
+- ASSERT(sdret != -BCME_PENDING);
+-
+- /* Control frame failures need
+- retransmission */
+- if (sdret < 0) {
+- DHD_ERROR(("%s: read %d control bytes failed: %d\n",
+- __func__,
+- rdlen, sdret));
+- /* dhd.rx_ctlerrs is higher */
+- bus->rxc_errors++;
+- dhd_os_sdunlock_rxq(bus->dhd);
+- dhdsdio_rxfail(bus, true,
+- (bus->bus ==
+- SPI_BUS) ? false
+- : true);
+- continue;
+- }
+- } else {
+- /* Give up on data,
+- request rtx of events */
+- DHD_ERROR(("%s (nextlen): "
+- "bcm_pkt_buf_get_skb failed:"
+- " len %d rdlen %d expected"
+- " rxseq %d\n", __func__,
+- len, rdlen, rxseq));
+- /* Just go try again w/normal
+- header read */
+- dhd_os_sdunlock_rxq(bus->dhd);
+- continue;
+- }
+- } else {
+- if (bus->bus == SPI_BUS)
+- bus->usebufpool = true;
+-
+- ASSERT(!(pkt->prev));
+- PKTALIGN(pkt, rdlen, DHD_SDALIGN);
+- rxbuf = (u8 *) (pkt->data);
+- /* Read the entire frame */
+- sdret = bcmsdh_recv_buf(bus,
+- bcmsdh_cur_sbwad(sdh),
+- SDIO_FUNC_2, F2SYNC,
+- rxbuf, rdlen,
+- pkt, NULL, NULL);
+- bus->f2rxdata++;
+- ASSERT(sdret != -BCME_PENDING);
+-
+- if (sdret < 0) {
+- DHD_ERROR(("%s (nextlen): read %d bytes failed: %d\n",
+- __func__, rdlen, sdret));
+- bcm_pkt_buf_free_skb(pkt);
+- bus->dhd->rx_errors++;
+- dhd_os_sdunlock_rxq(bus->dhd);
+- /* Force retry w/normal header read.
+- * Don't attempt NAK for
+- * gSPI
+- */
+- dhdsdio_rxfail(bus, true,
+- (bus->bus ==
+- SPI_BUS) ? false :
+- true);
+- continue;
+- }
+- }
+- dhd_os_sdunlock_rxq(bus->dhd);
+-
+- /* Now check the header */
+- memcpy(bus->rxhdr, rxbuf, SDPCM_HDRLEN);
+-
+- /* Extract hardware header fields */
+- len = get_unaligned_le16(bus->rxhdr);
+- check = get_unaligned_le16(bus->rxhdr + sizeof(u16));
+-
+- /* All zeros means readahead info was bad */
+- if (!(len | check)) {
+- DHD_INFO(("%s (nextlen): read zeros in HW "
+- "header???\n", __func__));
+- dhdsdio_pktfree2(bus, pkt);
+- continue;
+- }
+-
+- /* Validate check bytes */
+- if ((u16)~(len ^ check)) {
+- DHD_ERROR(("%s (nextlen): HW hdr error:"
+- " nextlen/len/check"
+- " 0x%04x/0x%04x/0x%04x\n",
+- __func__, nextlen, len, check));
+- bus->rx_badhdr++;
+- dhdsdio_rxfail(bus, false, false);
+- dhdsdio_pktfree2(bus, pkt);
+- continue;
+- }
+-
+- /* Validate frame length */
+- if (len < SDPCM_HDRLEN) {
+- DHD_ERROR(("%s (nextlen): HW hdr length "
+- "invalid: %d\n", __func__, len));
+- dhdsdio_pktfree2(bus, pkt);
+- continue;
+- }
+-
+- /* Check for consistency withreadahead info */
+- len_consistent = (nextlen != (roundup(len, 16) >> 4));
+- if (len_consistent) {
+- /* Mismatch, force retry w/normal
+- header (may be >4K) */
+- DHD_ERROR(("%s (nextlen): mismatch, "
+- "nextlen %d len %d rnd %d; "
+- "expected rxseq %d\n",
+- __func__, nextlen,
+- len, roundup(len, 16), rxseq));
+- dhdsdio_rxfail(bus, true, (bus->bus != SPI_BUS));
+- dhdsdio_pktfree2(bus, pkt);
+- continue;
+- }
+-
+- /* Extract software header fields */
+- chan = SDPCM_PACKET_CHANNEL(
+- &bus->rxhdr[SDPCM_FRAMETAG_LEN]);
+- seq = SDPCM_PACKET_SEQUENCE(
+- &bus->rxhdr[SDPCM_FRAMETAG_LEN]);
+- doff = SDPCM_DOFFSET_VALUE(
+- &bus->rxhdr[SDPCM_FRAMETAG_LEN]);
+- txmax = SDPCM_WINDOW_VALUE(
+- &bus->rxhdr[SDPCM_FRAMETAG_LEN]);
+-
+- bus->nextlen =
+- bus->rxhdr[SDPCM_FRAMETAG_LEN +
+- SDPCM_NEXTLEN_OFFSET];
+- if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
+- DHD_INFO(("%s (nextlen): got frame w/nextlen too large" " (%d), seq %d\n",
+- __func__, bus->nextlen, seq));
+- bus->nextlen = 0;
+- }
+-
+- bus->dhd->rx_readahead_cnt++;
+-
+- /* Handle Flow Control */
+- fcbits = SDPCM_FCMASK_VALUE(
+- &bus->rxhdr[SDPCM_FRAMETAG_LEN]);
+-
+- if (bus->flowcontrol != fcbits) {
+- if (~bus->flowcontrol & fcbits)
+- bus->fc_xoff++;
+-
+- if (bus->flowcontrol & ~fcbits)
+- bus->fc_xon++;
+-
+- bus->fc_rcvd++;
+- bus->flowcontrol = fcbits;
+- }
+-
+- /* Check and update sequence number */
+- if (rxseq != seq) {
+- DHD_INFO(("%s (nextlen): rx_seq %d, expected "
+- "%d\n", __func__, seq, rxseq));
+- bus->rx_badseq++;
+- rxseq = seq;
+- }
+-
+- /* Check window for sanity */
+- if ((u8) (txmax - bus->tx_seq) > 0x40) {
+- DHD_ERROR(("%s: got unlikely tx max %d with "
+- "tx_seq %d\n",
+- __func__, txmax, bus->tx_seq));
+- txmax = bus->tx_seq + 2;
+- }
+- bus->tx_max = txmax;
+-
+-#ifdef DHD_DEBUG
+- if (DHD_BYTES_ON() && DHD_DATA_ON()) {
+- printk(KERN_DEBUG "Rx Data:\n");
+- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
+- rxbuf, len);
+- } else if (DHD_HDRS_ON()) {
+- printk(KERN_DEBUG "RxHdr:\n");
+- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
+- bus->rxhdr, SDPCM_HDRLEN);
+- }
+-#endif
+-
+- if (chan == SDPCM_CONTROL_CHANNEL) {
+- if (bus->bus == SPI_BUS) {
+- dhdsdio_read_control(bus, rxbuf, len,
+- doff);
+- } else {
+- DHD_ERROR(("%s (nextlen): readahead on control" " packet %d?\n",
+- __func__, seq));
+- /* Force retry w/normal header read */
+- bus->nextlen = 0;
+- dhdsdio_rxfail(bus, false, true);
+- }
+- dhdsdio_pktfree2(bus, pkt);
+- continue;
+- }
+-
+- if ((bus->bus == SPI_BUS) && !bus->usebufpool) {
+- DHD_ERROR(("Received %d bytes on %d channel. Running out of " "rx pktbuf's or not yet malloced.\n",
+- len, chan));
+- continue;
+- }
+-
+- /* Validate data offset */
+- if ((doff < SDPCM_HDRLEN) || (doff > len)) {
+- DHD_ERROR(("%s (nextlen): bad data offset %d: HW len %d min %d\n",
+- __func__, doff, len, SDPCM_HDRLEN));
+- dhdsdio_rxfail(bus, false, false);
+- dhdsdio_pktfree2(bus, pkt);
+- continue;
+- }
+-
+- /* All done with this one -- now deliver the packet */
+- goto deliver;
+- }
+- /* gSPI frames should not be handled in fractions */
+- if (bus->bus == SPI_BUS)
+- break;
+-
+- /* Read frame header (hardware and software) */
+- sdret = bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh),
+- SDIO_FUNC_2, F2SYNC, bus->rxhdr, firstread,
+- NULL, NULL, NULL);
+- bus->f2rxhdrs++;
+- ASSERT(sdret != -BCME_PENDING);
+-
+- if (sdret < 0) {
+- DHD_ERROR(("%s: RXHEADER FAILED: %d\n", __func__,
+- sdret));
+- bus->rx_hdrfail++;
+- dhdsdio_rxfail(bus, true, true);
+- continue;
+- }
+-#ifdef DHD_DEBUG
+- if (DHD_BYTES_ON() || DHD_HDRS_ON()) {
+- printk(KERN_DEBUG "RxHdr:\n");
+- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
+- bus->rxhdr, SDPCM_HDRLEN);
+- }
+-#endif
+-
+- /* Extract hardware header fields */
+- len = get_unaligned_le16(bus->rxhdr);
+- check = get_unaligned_le16(bus->rxhdr + sizeof(u16));
+-
+- /* All zeros means no more frames */
+- if (!(len | check)) {
+- *finished = true;
+- break;
+- }
+-
+- /* Validate check bytes */
+- if ((u16) ~(len ^ check)) {
+- DHD_ERROR(("%s: HW hdr err: len/check 0x%04x/0x%04x\n",
+- __func__, len, check));
+- bus->rx_badhdr++;
+- dhdsdio_rxfail(bus, false, false);
+- continue;
+- }
+-
+- /* Validate frame length */
+- if (len < SDPCM_HDRLEN) {
+- DHD_ERROR(("%s: HW hdr length invalid: %d\n",
+- __func__, len));
+- continue;
+- }
+-
+- /* Extract software header fields */
+- chan = SDPCM_PACKET_CHANNEL(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
+- seq = SDPCM_PACKET_SEQUENCE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
+- doff = SDPCM_DOFFSET_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
+- txmax = SDPCM_WINDOW_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
+-
+- /* Validate data offset */
+- if ((doff < SDPCM_HDRLEN) || (doff > len)) {
+- DHD_ERROR(("%s: Bad data offset %d: HW len %d, min %d "
+- "seq %d\n",
+- __func__, doff, len, SDPCM_HDRLEN, seq));
+- bus->rx_badhdr++;
+- ASSERT(0);
+- dhdsdio_rxfail(bus, false, false);
+- continue;
+- }
+-
+- /* Save the readahead length if there is one */
+- bus->nextlen =
+- bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
+- if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
+- DHD_INFO(("%s (nextlen): got frame w/nextlen too large "
+- "(%d), seq %d\n",
+- __func__, bus->nextlen, seq));
+- bus->nextlen = 0;
+- }
+-
+- /* Handle Flow Control */
+- fcbits = SDPCM_FCMASK_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
+-
+- if (bus->flowcontrol != fcbits) {
+- if (~bus->flowcontrol & fcbits)
+- bus->fc_xoff++;
+-
+- if (bus->flowcontrol & ~fcbits)
+- bus->fc_xon++;
+-
+- bus->fc_rcvd++;
+- bus->flowcontrol = fcbits;
+- }
+-
+- /* Check and update sequence number */
+- if (rxseq != seq) {
+- DHD_INFO(("%s: rx_seq %d, expected %d\n", __func__,
+- seq, rxseq));
+- bus->rx_badseq++;
+- rxseq = seq;
+- }
+-
+- /* Check window for sanity */
+- if ((u8) (txmax - bus->tx_seq) > 0x40) {
+- DHD_ERROR(("%s: unlikely tx max %d with tx_seq %d\n",
+- __func__, txmax, bus->tx_seq));
+- txmax = bus->tx_seq + 2;
+- }
+- bus->tx_max = txmax;
+-
+- /* Call a separate function for control frames */
+- if (chan == SDPCM_CONTROL_CHANNEL) {
+- dhdsdio_read_control(bus, bus->rxhdr, len, doff);
+- continue;
+- }
+-
+- ASSERT((chan == SDPCM_DATA_CHANNEL)
+- || (chan == SDPCM_EVENT_CHANNEL)
+- || (chan == SDPCM_TEST_CHANNEL)
+- || (chan == SDPCM_GLOM_CHANNEL));
+-
+- /* Length to read */
+- rdlen = (len > firstread) ? (len - firstread) : 0;
+-
+- /* May pad read to blocksize for efficiency */
+- if (bus->roundup && bus->blocksize &&
+- (rdlen > bus->blocksize)) {
+- pad = bus->blocksize - (rdlen % bus->blocksize);
+- if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
+- ((rdlen + pad + firstread) < MAX_RX_DATASZ))
+- rdlen += pad;
+- } else if (rdlen % DHD_SDALIGN) {
+- rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN);
+- }
+-
+- /* Satisfy length-alignment requirements */
+- if (forcealign && (rdlen & (ALIGNMENT - 1)))
+- rdlen = roundup(rdlen, ALIGNMENT);
+-
+- if ((rdlen + firstread) > MAX_RX_DATASZ) {
+- /* Too long -- skip this frame */
+- DHD_ERROR(("%s: too long: len %d rdlen %d\n",
+- __func__, len, rdlen));
+- bus->dhd->rx_errors++;
+- bus->rx_toolong++;
+- dhdsdio_rxfail(bus, false, false);
+- continue;
+- }
+-
+- dhd_os_sdlock_rxq(bus->dhd);
+- pkt = bcm_pkt_buf_get_skb(rdlen + firstread + DHD_SDALIGN);
+- if (!pkt) {
+- /* Give up on data, request rtx of events */
+- DHD_ERROR(("%s: bcm_pkt_buf_get_skb failed: rdlen %d "
+- "chan %d\n", __func__, rdlen, chan));
+- bus->dhd->rx_dropped++;
+- dhd_os_sdunlock_rxq(bus->dhd);
+- dhdsdio_rxfail(bus, false, RETRYCHAN(chan));
+- continue;
+- }
+- dhd_os_sdunlock_rxq(bus->dhd);
+-
+- ASSERT(!(pkt->prev));
+-
+- /* Leave room for what we already read, and align remainder */
+- ASSERT(firstread < pkt->len);
+- skb_pull(pkt, firstread);
+- PKTALIGN(pkt, rdlen, DHD_SDALIGN);
+-
+- /* Read the remaining frame data */
+- sdret = bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2,
+- F2SYNC, ((u8 *) (pkt->data)), rdlen,
+- pkt, NULL, NULL);
+- bus->f2rxdata++;
+- ASSERT(sdret != -BCME_PENDING);
+-
+- if (sdret < 0) {
+- DHD_ERROR(("%s: read %d %s bytes failed: %d\n",
+- __func__, rdlen,
+- ((chan ==
+- SDPCM_EVENT_CHANNEL) ? "event" : ((chan ==
+- SDPCM_DATA_CHANNEL)
+- ? "data" : "test")),
+- sdret));
+- dhd_os_sdlock_rxq(bus->dhd);
+- bcm_pkt_buf_free_skb(pkt);
+- dhd_os_sdunlock_rxq(bus->dhd);
+- bus->dhd->rx_errors++;
+- dhdsdio_rxfail(bus, true, RETRYCHAN(chan));
+- continue;
+- }
+-
+- /* Copy the already-read portion */
+- skb_push(pkt, firstread);
+- memcpy(pkt->data, bus->rxhdr, firstread);
+-
+-#ifdef DHD_DEBUG
+- if (DHD_BYTES_ON() && DHD_DATA_ON()) {
+- printk(KERN_DEBUG "Rx Data:\n");
+- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
+- pkt->data, len);
+- }
+-#endif
+-
+-deliver:
+- /* Save superframe descriptor and allocate packet frame */
+- if (chan == SDPCM_GLOM_CHANNEL) {
+- if (SDPCM_GLOMDESC(&bus->rxhdr[SDPCM_FRAMETAG_LEN])) {
+- DHD_GLOM(("%s: glom descriptor, %d bytes:\n",
+- __func__, len));
+-#ifdef DHD_DEBUG
+- if (DHD_GLOM_ON()) {
+- printk(KERN_DEBUG "Glom Data:\n");
+- print_hex_dump_bytes("",
+- DUMP_PREFIX_OFFSET,
+- pkt->data, len);
+- }
+-#endif
+- __skb_trim(pkt, len);
+- ASSERT(doff == SDPCM_HDRLEN);
+- skb_pull(pkt, SDPCM_HDRLEN);
+- bus->glomd = pkt;
+- } else {
+- DHD_ERROR(("%s: glom superframe w/o "
+- "descriptor!\n", __func__));
+- dhdsdio_rxfail(bus, false, false);
+- }
+- continue;
+- }
+-
+- /* Fill in packet len and prio, deliver upward */
+- __skb_trim(pkt, len);
+- skb_pull(pkt, doff);
+-
+-#ifdef SDTEST
+- /* Test channel packets are processed separately */
+- if (chan == SDPCM_TEST_CHANNEL) {
+- dhdsdio_testrcv(bus, pkt, seq);
+- continue;
+- }
+-#endif /* SDTEST */
+-
+- if (pkt->len == 0) {
+- dhd_os_sdlock_rxq(bus->dhd);
+- bcm_pkt_buf_free_skb(pkt);
+- dhd_os_sdunlock_rxq(bus->dhd);
+- continue;
+- } else if (dhd_prot_hdrpull(bus->dhd, &ifidx, pkt) != 0) {
+- DHD_ERROR(("%s: rx protocol error\n", __func__));
+- dhd_os_sdlock_rxq(bus->dhd);
+- bcm_pkt_buf_free_skb(pkt);
+- dhd_os_sdunlock_rxq(bus->dhd);
+- bus->dhd->rx_errors++;
+- continue;
+- }
+-
+- /* Unlock during rx call */
+- dhd_os_sdunlock(bus->dhd);
+- dhd_rx_frame(bus->dhd, ifidx, pkt, 1);
+- dhd_os_sdlock(bus->dhd);
+- }
+- rxcount = maxframes - rxleft;
+-#ifdef DHD_DEBUG
+- /* Message if we hit the limit */
+- if (!rxleft && !sdtest)
+- DHD_DATA(("%s: hit rx limit of %d frames\n", __func__,
+- maxframes));
+- else
+-#endif /* DHD_DEBUG */
+- DHD_DATA(("%s: processed %d frames\n", __func__, rxcount));
+- /* Back off rxseq if awaiting rtx, update rx_seq */
+- if (bus->rxskip)
+- rxseq--;
+- bus->rx_seq = rxseq;
+-
+- return rxcount;
+-}
+-
+-static u32 dhdsdio_hostmail(dhd_bus_t *bus)
+-{
+- sdpcmd_regs_t *regs = bus->regs;
+- u32 intstatus = 0;
+- u32 hmb_data;
+- u8 fcbits;
+- uint retries = 0;
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- /* Read mailbox data and ack that we did so */
+- R_SDREG(hmb_data, ®s->tohostmailboxdata, retries);
+- if (retries <= retry_limit)
+- W_SDREG(SMB_INT_ACK, ®s->tosbmailbox, retries);
+- bus->f1regdata += 2;
+-
+- /* Dongle recomposed rx frames, accept them again */
+- if (hmb_data & HMB_DATA_NAKHANDLED) {
+- DHD_INFO(("Dongle reports NAK handled, expect rtx of %d\n",
+- bus->rx_seq));
+- if (!bus->rxskip)
+- DHD_ERROR(("%s: unexpected NAKHANDLED!\n", __func__));
+-
+- bus->rxskip = false;
+- intstatus |= I_HMB_FRAME_IND;
+- }
+-
+- /*
+- * DEVREADY does not occur with gSPI.
+- */
+- if (hmb_data & (HMB_DATA_DEVREADY | HMB_DATA_FWREADY)) {
+- bus->sdpcm_ver =
+- (hmb_data & HMB_DATA_VERSION_MASK) >>
+- HMB_DATA_VERSION_SHIFT;
+- if (bus->sdpcm_ver != SDPCM_PROT_VERSION)
+- DHD_ERROR(("Version mismatch, dongle reports %d, "
+- "expecting %d\n",
+- bus->sdpcm_ver, SDPCM_PROT_VERSION));
+- else
+- DHD_INFO(("Dongle ready, protocol version %d\n",
+- bus->sdpcm_ver));
+- }
+-
+- /*
+- * Flow Control has been moved into the RX headers and this out of band
+- * method isn't used any more.
+- * remaining backward compatible with older dongles.
+- */
+- if (hmb_data & HMB_DATA_FC) {
+- fcbits = (hmb_data & HMB_DATA_FCDATA_MASK) >>
+- HMB_DATA_FCDATA_SHIFT;
+-
+- if (fcbits & ~bus->flowcontrol)
+- bus->fc_xoff++;
+-
+- if (bus->flowcontrol & ~fcbits)
+- bus->fc_xon++;
+-
+- bus->fc_rcvd++;
+- bus->flowcontrol = fcbits;
+- }
+-
+- /* Shouldn't be any others */
+- if (hmb_data & ~(HMB_DATA_DEVREADY |
+- HMB_DATA_NAKHANDLED |
+- HMB_DATA_FC |
+- HMB_DATA_FWREADY |
+- HMB_DATA_FCDATA_MASK | HMB_DATA_VERSION_MASK)) {
+- DHD_ERROR(("Unknown mailbox data content: 0x%02x\n", hmb_data));
+- }
+-
+- return intstatus;
+-}
+-
+-bool dhdsdio_dpc(dhd_bus_t *bus)
+-{
+- bcmsdh_info_t *sdh = bus->sdh;
+- sdpcmd_regs_t *regs = bus->regs;
+- u32 intstatus, newstatus = 0;
+- uint retries = 0;
+- uint rxlimit = dhd_rxbound; /* Rx frames to read before resched */
+- uint txlimit = dhd_txbound; /* Tx frames to send before resched */
+- uint framecnt = 0; /* Temporary counter of tx/rx frames */
+- bool rxdone = true; /* Flag for no more read data */
+- bool resched = false; /* Flag indicating resched wanted */
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- /* Start with leftover status bits */
+- intstatus = bus->intstatus;
+-
+- dhd_os_sdlock(bus->dhd);
+-
+- /* If waiting for HTAVAIL, check status */
+- if (bus->clkstate == CLK_PENDING) {
+- int err;
+- u8 clkctl, devctl = 0;
+-
+-#ifdef DHD_DEBUG
+- /* Check for inconsistent device control */
+- devctl =
+- bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
+- if (err) {
+- DHD_ERROR(("%s: error reading DEVCTL: %d\n",
+- __func__, err));
+- bus->dhd->busstate = DHD_BUS_DOWN;
+- } else {
+- ASSERT(devctl & SBSDIO_DEVCTL_CA_INT_ONLY);
+- }
+-#endif /* DHD_DEBUG */
+-
+- /* Read CSR, if clock on switch to AVAIL, else ignore */
+- clkctl =
+- bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
+- &err);
+- if (err) {
+- DHD_ERROR(("%s: error reading CSR: %d\n", __func__,
+- err));
+- bus->dhd->busstate = DHD_BUS_DOWN;
+- }
+-
+- DHD_INFO(("DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n", devctl,
+- clkctl));
+-
+- if (SBSDIO_HTAV(clkctl)) {
+- devctl =
+- bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
+- &err);
+- if (err) {
+- DHD_ERROR(("%s: error reading DEVCTL: %d\n",
+- __func__, err));
+- bus->dhd->busstate = DHD_BUS_DOWN;
+- }
+- devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
+- bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
+- devctl, &err);
+- if (err) {
+- DHD_ERROR(("%s: error writing DEVCTL: %d\n",
+- __func__, err));
+- bus->dhd->busstate = DHD_BUS_DOWN;
+- }
+- bus->clkstate = CLK_AVAIL;
+- } else {
+- goto clkwait;
+- }
+- }
+-
+- BUS_WAKE(bus);
+-
+- /* Make sure backplane clock is on */
+- dhdsdio_clkctl(bus, CLK_AVAIL, true);
+- if (bus->clkstate == CLK_PENDING)
+- goto clkwait;
+-
+- /* Pending interrupt indicates new device status */
+- if (bus->ipend) {
+- bus->ipend = false;
+- R_SDREG(newstatus, ®s->intstatus, retries);
+- bus->f1regdata++;
+- if (bcmsdh_regfail(bus->sdh))
+- newstatus = 0;
+- newstatus &= bus->hostintmask;
+- bus->fcstate = !!(newstatus & I_HMB_FC_STATE);
+- if (newstatus) {
+- W_SDREG(newstatus, ®s->intstatus, retries);
+- bus->f1regdata++;
+- }
+- }
+-
+- /* Merge new bits with previous */
+- intstatus |= newstatus;
+- bus->intstatus = 0;
+-
+- /* Handle flow-control change: read new state in case our ack
+- * crossed another change interrupt. If change still set, assume
+- * FC ON for safety, let next loop through do the debounce.
+- */
+- if (intstatus & I_HMB_FC_CHANGE) {
+- intstatus &= ~I_HMB_FC_CHANGE;
+- W_SDREG(I_HMB_FC_CHANGE, ®s->intstatus, retries);
+- R_SDREG(newstatus, ®s->intstatus, retries);
+- bus->f1regdata += 2;
+- bus->fcstate =
+- !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE));
+- intstatus |= (newstatus & bus->hostintmask);
+- }
+-
+- /* Handle host mailbox indication */
+- if (intstatus & I_HMB_HOST_INT) {
+- intstatus &= ~I_HMB_HOST_INT;
+- intstatus |= dhdsdio_hostmail(bus);
+- }
+-
+- /* Generally don't ask for these, can get CRC errors... */
+- if (intstatus & I_WR_OOSYNC) {
+- DHD_ERROR(("Dongle reports WR_OOSYNC\n"));
+- intstatus &= ~I_WR_OOSYNC;
+- }
+-
+- if (intstatus & I_RD_OOSYNC) {
+- DHD_ERROR(("Dongle reports RD_OOSYNC\n"));
+- intstatus &= ~I_RD_OOSYNC;
+- }
+-
+- if (intstatus & I_SBINT) {
+- DHD_ERROR(("Dongle reports SBINT\n"));
+- intstatus &= ~I_SBINT;
+- }
+-
+- /* Would be active due to wake-wlan in gSPI */
+- if (intstatus & I_CHIPACTIVE) {
+- DHD_INFO(("Dongle reports CHIPACTIVE\n"));
+- intstatus &= ~I_CHIPACTIVE;
+- }
+-
+- /* Ignore frame indications if rxskip is set */
+- if (bus->rxskip)
+- intstatus &= ~I_HMB_FRAME_IND;
+-
+- /* On frame indication, read available frames */
+- if (PKT_AVAILABLE()) {
+- framecnt = dhdsdio_readframes(bus, rxlimit, &rxdone);
+- if (rxdone || bus->rxskip)
+- intstatus &= ~I_HMB_FRAME_IND;
+- rxlimit -= min(framecnt, rxlimit);
+- }
+-
+- /* Keep still-pending events for next scheduling */
+- bus->intstatus = intstatus;
+-
+-clkwait:
+-#if defined(OOB_INTR_ONLY)
+- bcmsdh_oob_intr_set(1);
+-#endif /* (OOB_INTR_ONLY) */
+- /* Re-enable interrupts to detect new device events (mailbox, rx frame)
+- * or clock availability. (Allows tx loop to check ipend if desired.)
+- * (Unless register access seems hosed, as we may not be able to ACK...)
+- */
+- if (bus->intr && bus->intdis && !bcmsdh_regfail(sdh)) {
+- DHD_INTR(("%s: enable SDIO interrupts, rxdone %d framecnt %d\n",
+- __func__, rxdone, framecnt));
+- bus->intdis = false;
+- bcmsdh_intr_enable(sdh);
+- }
+-
+- if (DATAOK(bus) && bus->ctrl_frame_stat &&
+- (bus->clkstate == CLK_AVAIL)) {
+- int ret, i;
+-
+- ret =
+- dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2,
+- F2SYNC, (u8 *) bus->ctrl_frame_buf,
+- (u32) bus->ctrl_frame_len, NULL,
+- NULL, NULL);
+- ASSERT(ret != -BCME_PENDING);
+-
+- if (ret < 0) {
+- /* On failure, abort the command and
+- terminate the frame */
+- DHD_INFO(("%s: sdio error %d, abort command and "
+- "terminate frame.\n", __func__, ret));
+- bus->tx_sderrs++;
+-
+- bcmsdh_abort(sdh, SDIO_FUNC_2);
+-
+- bcmsdh_cfg_write(sdh, SDIO_FUNC_1,
+- SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM,
+- NULL);
+- bus->f1regdata++;
+-
+- for (i = 0; i < 3; i++) {
+- u8 hi, lo;
+- hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
+- SBSDIO_FUNC1_WFRAMEBCHI,
+- NULL);
+- lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
+- SBSDIO_FUNC1_WFRAMEBCLO,
+- NULL);
+- bus->f1regdata += 2;
+- if ((hi == 0) && (lo == 0))
+- break;
+- }
+-
+- }
+- if (ret == 0)
+- bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
+-
+- DHD_INFO(("Return_dpc value is : %d\n", ret));
+- bus->ctrl_frame_stat = false;
+- dhd_wait_event_wakeup(bus->dhd);
+- }
+- /* Send queued frames (limit 1 if rx may still be pending) */
+- else if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate &&
+- bcm_pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit
+- && DATAOK(bus)) {
+- framecnt = rxdone ? txlimit : min(txlimit, dhd_txminmax);
+- framecnt = dhdsdio_sendfromq(bus, framecnt);
+- txlimit -= framecnt;
+- }
+-
+- /* Resched if events or tx frames are pending,
+- else await next interrupt */
+- /* On failed register access, all bets are off:
+- no resched or interrupts */
+- if ((bus->dhd->busstate == DHD_BUS_DOWN) || bcmsdh_regfail(sdh)) {
+- DHD_ERROR(("%s: failed backplane access over SDIO, halting "
+- "operation %d\n", __func__, bcmsdh_regfail(sdh)));
+- bus->dhd->busstate = DHD_BUS_DOWN;
+- bus->intstatus = 0;
+- } else if (bus->clkstate == CLK_PENDING) {
+- DHD_INFO(("%s: rescheduled due to CLK_PENDING awaiting "
+- "I_CHIPACTIVE interrupt\n", __func__));
+- resched = true;
+- } else if (bus->intstatus || bus->ipend ||
+- (!bus->fcstate && bcm_pktq_mlen(&bus->txq, ~bus->flowcontrol) &&
+- DATAOK(bus)) || PKT_AVAILABLE()) {
+- resched = true;
+- }
+-
+- bus->dpc_sched = resched;
+-
+- /* If we're done for now, turn off clock request. */
+- if ((bus->clkstate != CLK_PENDING)
+- && bus->idletime == DHD_IDLE_IMMEDIATE) {
+- bus->activity = false;
+- dhdsdio_clkctl(bus, CLK_NONE, false);
+- }
+-
+- dhd_os_sdunlock(bus->dhd);
+-
+- return resched;
+-}
+-
+-bool dhd_bus_dpc(struct dhd_bus *bus)
+-{
+- bool resched;
+-
+- /* Call the DPC directly. */
+- DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __func__));
+- resched = dhdsdio_dpc(bus);
+-
+- return resched;
+-}
+-
+-void dhdsdio_isr(void *arg)
+-{
+- dhd_bus_t *bus = (dhd_bus_t *) arg;
+- bcmsdh_info_t *sdh;
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- if (!bus) {
+- DHD_ERROR(("%s : bus is null pointer , exit\n", __func__));
+- return;
+- }
+- sdh = bus->sdh;
+-
+- if (bus->dhd->busstate == DHD_BUS_DOWN) {
+- DHD_ERROR(("%s : bus is down. we have nothing to do\n",
+- __func__));
+- return;
+- }
+- /* Count the interrupt call */
+- bus->intrcount++;
+- bus->ipend = true;
+-
+- /* Shouldn't get this interrupt if we're sleeping? */
+- if (bus->sleeping) {
+- DHD_ERROR(("INTERRUPT WHILE SLEEPING??\n"));
+- return;
+- }
+-
+- /* Disable additional interrupts (is this needed now)? */
+- if (bus->intr)
+- DHD_INTR(("%s: disable SDIO interrupts\n", __func__));
+- else
+- DHD_ERROR(("dhdsdio_isr() w/o interrupt configured!\n"));
+-
+- bcmsdh_intr_disable(sdh);
+- bus->intdis = true;
+-
+-#if defined(SDIO_ISR_THREAD)
+- DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __func__));
+- while (dhdsdio_dpc(bus))
+- ;
+-#else
+- bus->dpc_sched = true;
+- dhd_sched_dpc(bus->dhd);
+-#endif
+-
+-}
+-
+-#ifdef SDTEST
+-static void dhdsdio_pktgen_init(dhd_bus_t *bus)
+-{
+- /* Default to specified length, or full range */
+- if (dhd_pktgen_len) {
+- bus->pktgen_maxlen = min(dhd_pktgen_len, MAX_PKTGEN_LEN);
+- bus->pktgen_minlen = bus->pktgen_maxlen;
+- } else {
+- bus->pktgen_maxlen = MAX_PKTGEN_LEN;
+- bus->pktgen_minlen = 0;
+- }
+- bus->pktgen_len = (u16) bus->pktgen_minlen;
+-
+- /* Default to per-watchdog burst with 10s print time */
+- bus->pktgen_freq = 1;
+- bus->pktgen_print = 10000 / dhd_watchdog_ms;
+- bus->pktgen_count = (dhd_pktgen * dhd_watchdog_ms + 999) / 1000;
+-
+- /* Default to echo mode */
+- bus->pktgen_mode = DHD_PKTGEN_ECHO;
+- bus->pktgen_stop = 1;
+-}
+-
+-static void dhdsdio_pktgen(dhd_bus_t *bus)
+-{
+- struct sk_buff *pkt;
+- u8 *data;
+- uint pktcount;
+- uint fillbyte;
+- u16 len;
+-
+- /* Display current count if appropriate */
+- if (bus->pktgen_print && (++bus->pktgen_ptick >= bus->pktgen_print)) {
+- bus->pktgen_ptick = 0;
+- printk(KERN_DEBUG "%s: send attempts %d rcvd %d\n",
+- __func__, bus->pktgen_sent, bus->pktgen_rcvd);
+- }
+-
+- /* For recv mode, just make sure dongle has started sending */
+- if (bus->pktgen_mode == DHD_PKTGEN_RECV) {
+- if (!bus->pktgen_rcvd)
+- dhdsdio_sdtest_set(bus, true);
+- return;
+- }
+-
+- /* Otherwise, generate or request the specified number of packets */
+- for (pktcount = 0; pktcount < bus->pktgen_count; pktcount++) {
+- /* Stop if total has been reached */
+- if (bus->pktgen_total
+- && (bus->pktgen_sent >= bus->pktgen_total)) {
+- bus->pktgen_count = 0;
+- break;
+- }
+-
+- /* Allocate an appropriate-sized packet */
+- len = bus->pktgen_len;
+- pkt = bcm_pkt_buf_get_skb(
+- (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN),
+- true);
+- if (!pkt) {
+- DHD_ERROR(("%s: bcm_pkt_buf_get_skb failed!\n",
+- __func__));
+- break;
+- }
+- PKTALIGN(pkt, (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN),
+- DHD_SDALIGN);
+- data = (u8 *) (pkt->data) + SDPCM_HDRLEN;
+-
+- /* Write test header cmd and extra based on mode */
+- switch (bus->pktgen_mode) {
+- case DHD_PKTGEN_ECHO:
+- *data++ = SDPCM_TEST_ECHOREQ;
+- *data++ = (u8) bus->pktgen_sent;
+- break;
+-
+- case DHD_PKTGEN_SEND:
+- *data++ = SDPCM_TEST_DISCARD;
+- *data++ = (u8) bus->pktgen_sent;
+- break;
+-
+- case DHD_PKTGEN_RXBURST:
+- *data++ = SDPCM_TEST_BURST;
+- *data++ = (u8) bus->pktgen_count;
+- break;
+-
+- default:
+- DHD_ERROR(("Unrecognized pktgen mode %d\n",
+- bus->pktgen_mode));
+- bcm_pkt_buf_free_skb(pkt, true);
+- bus->pktgen_count = 0;
+- return;
+- }
+-
+- /* Write test header length field */
+- *data++ = (len >> 0);
+- *data++ = (len >> 8);
+-
+- /* Then fill in the remainder -- N/A for burst,
+- but who cares... */
+- for (fillbyte = 0; fillbyte < len; fillbyte++)
+- *data++ =
+- SDPCM_TEST_FILL(fillbyte, (u8) bus->pktgen_sent);
+-
+-#ifdef DHD_DEBUG
+- if (DHD_BYTES_ON() && DHD_DATA_ON()) {
+- data = (u8 *) (pkt->data) + SDPCM_HDRLEN;
+- printk(KERN_DEBUG "dhdsdio_pktgen: Tx Data:\n");
+- print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, data,
+- pkt->len - SDPCM_HDRLEN);
+- }
+-#endif
+-
+- /* Send it */
+- if (dhdsdio_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, true)) {
+- bus->pktgen_fail++;
+- if (bus->pktgen_stop
+- && bus->pktgen_stop == bus->pktgen_fail)
+- bus->pktgen_count = 0;
+- }
+- bus->pktgen_sent++;
+-
+- /* Bump length if not fixed, wrap at max */
+- if (++bus->pktgen_len > bus->pktgen_maxlen)
+- bus->pktgen_len = (u16) bus->pktgen_minlen;
+-
+- /* Special case for burst mode: just send one request! */
+- if (bus->pktgen_mode == DHD_PKTGEN_RXBURST)
+- break;
+- }
+-}
+-
+-static void dhdsdio_sdtest_set(dhd_bus_t *bus, bool start)
+-{
+- struct sk_buff *pkt;
+- u8 *data;
+-
+- /* Allocate the packet */
+- pkt = bcm_pkt_buf_get_skb(SDPCM_HDRLEN + SDPCM_TEST_HDRLEN +
+- DHD_SDALIGN, true);
+- if (!pkt) {
+- DHD_ERROR(("%s: bcm_pkt_buf_get_skb failed!\n", __func__));
+- return;
+- }
+- PKTALIGN(pkt, (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN), DHD_SDALIGN);
+- data = (u8 *) (pkt->data) + SDPCM_HDRLEN;
+-
+- /* Fill in the test header */
+- *data++ = SDPCM_TEST_SEND;
+- *data++ = start;
+- *data++ = (bus->pktgen_maxlen >> 0);
+- *data++ = (bus->pktgen_maxlen >> 8);
+-
+- /* Send it */
+- if (dhdsdio_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, true))
+- bus->pktgen_fail++;
+-}
+-
+-static void dhdsdio_testrcv(dhd_bus_t *bus, struct sk_buff *pkt, uint seq)
+-{
+- u8 *data;
+- uint pktlen;
+-
+- u8 cmd;
+- u8 extra;
+- u16 len;
+- u16 offset;
+-
+- /* Check for min length */
+- pktlen = pkt->len;
+- if (pktlen < SDPCM_TEST_HDRLEN) {
+- DHD_ERROR(("dhdsdio_restrcv: toss runt frame, pktlen %d\n",
+- pktlen));
+- bcm_pkt_buf_free_skb(pkt, false);
+- return;
+- }
+-
+- /* Extract header fields */
+- data = pkt->data;
+- cmd = *data++;
+- extra = *data++;
+- len = *data++;
+- len += *data++ << 8;
+-
+- /* Check length for relevant commands */
+- if (cmd == SDPCM_TEST_DISCARD || cmd == SDPCM_TEST_ECHOREQ
+- || cmd == SDPCM_TEST_ECHORSP) {
+- if (pktlen != len + SDPCM_TEST_HDRLEN) {
+- DHD_ERROR(("dhdsdio_testrcv: frame length mismatch, "
+- "pktlen %d seq %d" " cmd %d extra %d len %d\n",
+- pktlen, seq, cmd, extra, len));
+- bcm_pkt_buf_free_skb(pkt, false);
+- return;
+- }
+- }
+-
+- /* Process as per command */
+- switch (cmd) {
+- case SDPCM_TEST_ECHOREQ:
+- /* Rx->Tx turnaround ok (even on NDIS w/current
+- implementation) */
+- *(u8 *) (pkt->data) = SDPCM_TEST_ECHORSP;
+- if (dhdsdio_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, true) == 0) {
+- bus->pktgen_sent++;
+- } else {
+- bus->pktgen_fail++;
+- bcm_pkt_buf_free_skb(pkt, false);
+- }
+- bus->pktgen_rcvd++;
+- break;
+-
+- case SDPCM_TEST_ECHORSP:
+- if (bus->ext_loop) {
+- bcm_pkt_buf_free_skb(pkt, false);
+- bus->pktgen_rcvd++;
+- break;
+- }
+-
+- for (offset = 0; offset < len; offset++, data++) {
+- if (*data != SDPCM_TEST_FILL(offset, extra)) {
+- DHD_ERROR(("dhdsdio_testrcv: echo data mismatch: " "offset %d (len %d) expect 0x%02x rcvd 0x%02x\n",
+- offset, len,
+- SDPCM_TEST_FILL(offset, extra), *data));
+- break;
+- }
+- }
+- bcm_pkt_buf_free_skb(pkt, false);
+- bus->pktgen_rcvd++;
+- break;
+-
+- case SDPCM_TEST_DISCARD:
+- bcm_pkt_buf_free_skb(pkt, false);
+- bus->pktgen_rcvd++;
+- break;
+-
+- case SDPCM_TEST_BURST:
+- case SDPCM_TEST_SEND:
+- default:
+- DHD_INFO(("dhdsdio_testrcv: unsupported or unknown command, "
+- "pktlen %d seq %d" " cmd %d extra %d len %d\n",
+- pktlen, seq, cmd, extra, len));
+- bcm_pkt_buf_free_skb(pkt, false);
+- break;
+- }
+-
+- /* For recv mode, stop at limie (and tell dongle to stop sending) */
+- if (bus->pktgen_mode == DHD_PKTGEN_RECV) {
+- if (bus->pktgen_total
+- && (bus->pktgen_rcvd >= bus->pktgen_total)) {
+- bus->pktgen_count = 0;
+- dhdsdio_sdtest_set(bus, false);
+- }
+- }
+-}
+-#endif /* SDTEST */
+-
+-extern bool dhd_bus_watchdog(dhd_pub_t *dhdp)
+-{
+- dhd_bus_t *bus;
+-
+- DHD_TIMER(("%s: Enter\n", __func__));
+-
+- bus = dhdp->bus;
+-
+- if (bus->dhd->dongle_reset)
+- return false;
+-
+- /* Ignore the timer if simulating bus down */
+- if (bus->sleeping)
+- return false;
+-
+- dhd_os_sdlock(bus->dhd);
+-
+- /* Poll period: check device if appropriate. */
+- if (bus->poll && (++bus->polltick >= bus->pollrate)) {
+- u32 intstatus = 0;
+-
+- /* Reset poll tick */
+- bus->polltick = 0;
+-
+- /* Check device if no interrupts */
+- if (!bus->intr || (bus->intrcount == bus->lastintrs)) {
+-
+- if (!bus->dpc_sched) {
+- u8 devpend;
+- devpend = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0,
+- SDIOD_CCCR_INTPEND,
+- NULL);
+- intstatus =
+- devpend & (INTR_STATUS_FUNC1 |
+- INTR_STATUS_FUNC2);
+- }
+-
+- /* If there is something, make like the ISR and
+- schedule the DPC */
+- if (intstatus) {
+- bus->pollcnt++;
+- bus->ipend = true;
+- if (bus->intr)
+- bcmsdh_intr_disable(bus->sdh);
+-
+- bus->dpc_sched = true;
+- dhd_sched_dpc(bus->dhd);
+-
+- }
+- }
+-
+- /* Update interrupt tracking */
+- bus->lastintrs = bus->intrcount;
+- }
+-#ifdef DHD_DEBUG
+- /* Poll for console output periodically */
+- if (dhdp->busstate == DHD_BUS_DATA && dhd_console_ms != 0) {
+- bus->console.count += dhd_watchdog_ms;
+- if (bus->console.count >= dhd_console_ms) {
+- bus->console.count -= dhd_console_ms;
+- /* Make sure backplane clock is on */
+- dhdsdio_clkctl(bus, CLK_AVAIL, false);
+- if (dhdsdio_readconsole(bus) < 0)
+- dhd_console_ms = 0; /* On error,
+- stop trying */
+- }
+- }
+-#endif /* DHD_DEBUG */
+-
+-#ifdef SDTEST
+- /* Generate packets if configured */
+- if (bus->pktgen_count && (++bus->pktgen_tick >= bus->pktgen_freq)) {
+- /* Make sure backplane clock is on */
+- dhdsdio_clkctl(bus, CLK_AVAIL, false);
+- bus->pktgen_tick = 0;
+- dhdsdio_pktgen(bus);
+- }
+-#endif
+-
+- /* On idle timeout clear activity flag and/or turn off clock */
+- if ((bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) {
+- if (++bus->idlecount >= bus->idletime) {
+- bus->idlecount = 0;
+- if (bus->activity) {
+- bus->activity = false;
+- dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
+- } else {
+- dhdsdio_clkctl(bus, CLK_NONE, false);
+- }
+- }
+- }
+-
+- dhd_os_sdunlock(bus->dhd);
+-
+- return bus->ipend;
+-}
+-
+-#ifdef DHD_DEBUG
+-extern int dhd_bus_console_in(dhd_pub_t *dhdp, unsigned char *msg, uint msglen)
+-{
+- dhd_bus_t *bus = dhdp->bus;
+- u32 addr, val;
+- int rv;
+- struct sk_buff *pkt;
+-
+- /* Address could be zero if CONSOLE := 0 in dongle Makefile */
+- if (bus->console_addr == 0)
+- return -ENOTSUPP;
+-
+- /* Exclusive bus access */
+- dhd_os_sdlock(bus->dhd);
+-
+- /* Don't allow input if dongle is in reset */
+- if (bus->dhd->dongle_reset) {
+- dhd_os_sdunlock(bus->dhd);
+- return -EPERM;
+- }
+-
+- /* Request clock to allow SDIO accesses */
+- BUS_WAKE(bus);
+- /* No pend allowed since txpkt is called later, ht clk has to be on */
+- dhdsdio_clkctl(bus, CLK_AVAIL, false);
+-
+- /* Zero cbuf_index */
+- addr = bus->console_addr + offsetof(hndrte_cons_t, cbuf_idx);
+- val = cpu_to_le32(0);
+- rv = dhdsdio_membytes(bus, true, addr, (u8 *)&val, sizeof(val));
+- if (rv < 0)
+- goto done;
+-
+- /* Write message into cbuf */
+- addr = bus->console_addr + offsetof(hndrte_cons_t, cbuf);
+- rv = dhdsdio_membytes(bus, true, addr, (u8 *)msg, msglen);
+- if (rv < 0)
+- goto done;
+-
+- /* Write length into vcons_in */
+- addr = bus->console_addr + offsetof(hndrte_cons_t, vcons_in);
+- val = cpu_to_le32(msglen);
+- rv = dhdsdio_membytes(bus, true, addr, (u8 *)&val, sizeof(val));
+- if (rv < 0)
+- goto done;
+-
+- /* Bump dongle by sending an empty event pkt.
+- * sdpcm_sendup (RX) checks for virtual console input.
+- */
+- pkt = bcm_pkt_buf_get_skb(4 + SDPCM_RESERVE);
+- if ((pkt != NULL) && bus->clkstate == CLK_AVAIL)
+- dhdsdio_txpkt(bus, pkt, SDPCM_EVENT_CHANNEL, true);
+-
+-done:
+- if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
+- bus->activity = false;
+- dhdsdio_clkctl(bus, CLK_NONE, true);
+- }
+-
+- dhd_os_sdunlock(bus->dhd);
+-
+- return rv;
+-}
+-#endif /* DHD_DEBUG */
+-
+-#ifdef DHD_DEBUG
+-static void dhd_dump_cis(uint fn, u8 *cis)
+-{
+- uint byte, tag, tdata;
+- DHD_INFO(("Function %d CIS:\n", fn));
+-
+- for (tdata = byte = 0; byte < SBSDIO_CIS_SIZE_LIMIT; byte++) {
+- if ((byte % 16) == 0)
+- DHD_INFO((" "));
+- DHD_INFO(("%02x ", cis[byte]));
+- if ((byte % 16) == 15)
+- DHD_INFO(("\n"));
+- if (!tdata--) {
+- tag = cis[byte];
+- if (tag == 0xff)
+- break;
+- else if (!tag)
+- tdata = 0;
+- else if ((byte + 1) < SBSDIO_CIS_SIZE_LIMIT)
+- tdata = cis[byte + 1] + 1;
+- else
+- DHD_INFO(("]"));
+- }
+- }
+- if ((byte % 16) != 15)
+- DHD_INFO(("\n"));
+-}
+-#endif /* DHD_DEBUG */
+-
+-static bool dhdsdio_chipmatch(u16 chipid)
+-{
+- if (chipid == BCM4325_CHIP_ID)
+- return true;
+- if (chipid == BCM4329_CHIP_ID)
+- return true;
+- if (chipid == BCM4319_CHIP_ID)
+- return true;
+- return false;
+-}
+-
+-static void *dhdsdio_probe(u16 venid, u16 devid, u16 bus_no,
+- u16 slot, u16 func, uint bustype, void *regsva,
+- void *sdh)
+-{
+- int ret;
+- dhd_bus_t *bus;
+-
+- /* Init global variables at run-time, not as part of the declaration.
+- * This is required to support init/de-init of the driver.
+- * Initialization
+- * of globals as part of the declaration results in non-deterministic
+- * behavior since the value of the globals may be different on the
+- * first time that the driver is initialized vs subsequent
+- * initializations.
+- */
+- dhd_txbound = DHD_TXBOUND;
+- dhd_rxbound = DHD_RXBOUND;
+- dhd_alignctl = true;
+- sd1idle = true;
+- dhd_readahead = true;
+- retrydata = false;
+- dhd_dongle_memsize = 0;
+- dhd_txminmax = DHD_TXMINMAX;
+-
+- forcealign = true;
+-
+- dhd_common_init();
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+- DHD_INFO(("%s: venid 0x%04x devid 0x%04x\n", __func__, venid, devid));
+-
+- /* We make assumptions about address window mappings */
+- ASSERT((unsigned long)regsva == SI_ENUM_BASE);
+-
+- /* BCMSDH passes venid and devid based on CIS parsing -- but
+- * low-power start
+- * means early parse could fail, so here we should get either an ID
+- * we recognize OR (-1) indicating we must request power first.
+- */
+- /* Check the Vendor ID */
+- switch (venid) {
+- case 0x0000:
+- case PCI_VENDOR_ID_BROADCOM:
+- break;
+- default:
+- DHD_ERROR(("%s: unknown vendor: 0x%04x\n", __func__, venid));
+- return NULL;
+- }
+-
+- /* Check the Device ID and make sure it's one that we support */
+- switch (devid) {
+- case BCM4325_D11DUAL_ID: /* 4325 802.11a/g id */
+- case BCM4325_D11G_ID: /* 4325 802.11g 2.4Ghz band id */
+- case BCM4325_D11A_ID: /* 4325 802.11a 5Ghz band id */
+- DHD_INFO(("%s: found 4325 Dongle\n", __func__));
+- break;
+- case BCM4329_D11NDUAL_ID: /* 4329 802.11n dualband device */
+- case BCM4329_D11N2G_ID: /* 4329 802.11n 2.4G device */
+- case BCM4329_D11N5G_ID: /* 4329 802.11n 5G device */
+- case 0x4329:
+- DHD_INFO(("%s: found 4329 Dongle\n", __func__));
+- break;
+- case BCM4319_D11N_ID: /* 4319 802.11n id */
+- case BCM4319_D11N2G_ID: /* 4319 802.11n2g id */
+- case BCM4319_D11N5G_ID: /* 4319 802.11n5g id */
+- DHD_INFO(("%s: found 4319 Dongle\n", __func__));
+- break;
+- case 0:
+- DHD_INFO(("%s: allow device id 0, will check chip internals\n",
+- __func__));
+- break;
+-
+- default:
+- DHD_ERROR(("%s: skipping 0x%04x/0x%04x, not a dongle\n",
+- __func__, venid, devid));
+- return NULL;
+- }
+-
+- /* Allocate private bus interface state */
+- bus = kzalloc(sizeof(dhd_bus_t), GFP_ATOMIC);
+- if (!bus) {
+- DHD_ERROR(("%s: kmalloc of dhd_bus_t failed\n", __func__));
+- goto fail;
+- }
+- bus->sdh = sdh;
+- bus->cl_devid = (u16) devid;
+- bus->bus = DHD_BUS;
+- bus->tx_seq = SDPCM_SEQUENCE_WRAP - 1;
+- bus->usebufpool = false; /* Use bufpool if allocated,
+- else use locally malloced rxbuf */
+-
+- /* attempt to attach to the dongle */
+- if (!(dhdsdio_probe_attach(bus, sdh, regsva, devid))) {
+- DHD_ERROR(("%s: dhdsdio_probe_attach failed\n", __func__));
+- goto fail;
+- }
+-
+- /* Attach to the dhd/OS/network interface */
+- bus->dhd = dhd_attach(bus, SDPCM_RESERVE);
+- if (!bus->dhd) {
+- DHD_ERROR(("%s: dhd_attach failed\n", __func__));
+- goto fail;
+- }
+-
+- /* Allocate buffers */
+- if (!(dhdsdio_probe_malloc(bus, sdh))) {
+- DHD_ERROR(("%s: dhdsdio_probe_malloc failed\n", __func__));
+- goto fail;
+- }
+-
+- if (!(dhdsdio_probe_init(bus, sdh))) {
+- DHD_ERROR(("%s: dhdsdio_probe_init failed\n", __func__));
+- goto fail;
+- }
+-
+- /* Register interrupt callback, but mask it (not operational yet). */
+- DHD_INTR(("%s: disable SDIO interrupts (not interested yet)\n",
+- __func__));
+- bcmsdh_intr_disable(sdh);
+- ret = bcmsdh_intr_reg(sdh, dhdsdio_isr, bus);
+- if (ret != 0) {
+- DHD_ERROR(("%s: FAILED: bcmsdh_intr_reg returned %d\n",
+- __func__, ret));
+- goto fail;
+- }
+- DHD_INTR(("%s: registered SDIO interrupt function ok\n", __func__));
+-
+- DHD_INFO(("%s: completed!!\n", __func__));
+-
+- /* if firmware path present try to download and bring up bus */
+- ret = dhd_bus_start(bus->dhd);
+- if (ret != 0) {
+- if (ret == -ENOLINK) {
+- DHD_ERROR(("%s: dongle is not responding\n", __func__));
+- goto fail;
+- }
+- }
+- /* Ok, have the per-port tell the stack we're open for business */
+- if (dhd_net_attach(bus->dhd, 0) != 0) {
+- DHD_ERROR(("%s: Net attach failed!!\n", __func__));
+- goto fail;
+- }
+-
+- return bus;
+-
+-fail:
+- dhdsdio_release(bus);
+- return NULL;
+-}
+-
+-static bool
+-dhdsdio_probe_attach(struct dhd_bus *bus, void *sdh, void *regsva, u16 devid)
+-{
+- u8 clkctl = 0;
+- int err = 0;
+-
+- bus->alp_only = true;
+-
+- /* Return the window to backplane enumeration space for core access */
+- if (dhdsdio_set_siaddr_window(bus, SI_ENUM_BASE))
+- DHD_ERROR(("%s: FAILED to return to SI_ENUM_BASE\n", __func__));
+-
+-#ifdef DHD_DEBUG
+- printk(KERN_DEBUG "F1 signature read @0x18000000=0x%4x\n",
+- bcmsdh_reg_read(bus->sdh, SI_ENUM_BASE, 4));
+-
+-#endif /* DHD_DEBUG */
+-
+- /*
+- * Force PLL off until dhdsdio_chip_attach()
+- * programs PLL control regs
+- */
+-
+- bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
+- DHD_INIT_CLKCTL1, &err);
+- if (!err)
+- clkctl =
+- bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
+- &err);
+-
+- if (err || ((clkctl & ~SBSDIO_AVBITS) != DHD_INIT_CLKCTL1)) {
+- DHD_ERROR(("dhdsdio_probe: ChipClkCSR access: err %d wrote "
+- "0x%02x read 0x%02x\n",
+- err, DHD_INIT_CLKCTL1, clkctl));
+- goto fail;
+- }
+-#ifdef DHD_DEBUG
+- if (DHD_INFO_ON()) {
+- uint fn, numfn;
+- u8 *cis[SDIOD_MAX_IOFUNCS];
+- int err = 0;
+-
+- numfn = bcmsdh_query_iofnum(sdh);
+- ASSERT(numfn <= SDIOD_MAX_IOFUNCS);
+-
+- /* Make sure ALP is available before trying to read CIS */
+- SPINWAIT(((clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
+- SBSDIO_FUNC1_CHIPCLKCSR,
+- NULL)),
+- !SBSDIO_ALPAV(clkctl)), PMU_MAX_TRANSITION_DLY);
+-
+- /* Now request ALP be put on the bus */
+- bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
+- DHD_INIT_CLKCTL2, &err);
+- udelay(65);
+-
+- for (fn = 0; fn <= numfn; fn++) {
+- cis[fn] = kzalloc(SBSDIO_CIS_SIZE_LIMIT, GFP_ATOMIC);
+- if (!cis[fn]) {
+- DHD_INFO(("dhdsdio_probe: fn %d cis malloc "
+- "failed\n", fn));
+- break;
+- }
+-
+- err = bcmsdh_cis_read(sdh, fn, cis[fn],
+- SBSDIO_CIS_SIZE_LIMIT);
+- if (err) {
+- DHD_INFO(("dhdsdio_probe: fn %d cis read "
+- "err %d\n", fn, err));
+- kfree(cis[fn]);
+- break;
+- }
+- dhd_dump_cis(fn, cis[fn]);
+- }
+-
+- while (fn-- > 0) {
+- ASSERT(cis[fn]);
+- kfree(cis[fn]);
+- }
+-
+- if (err) {
+- DHD_ERROR(("dhdsdio_probe: error read/parsing CIS\n"));
+- goto fail;
+- }
+- }
+-#endif /* DHD_DEBUG */
+-
+- if (dhdsdio_chip_attach(bus, regsva)) {
+- DHD_ERROR(("%s: dhdsdio_chip_attach failed!\n", __func__));
+- goto fail;
+- }
+-
+- bcmsdh_chipinfo(sdh, bus->ci->chip, bus->ci->chiprev);
+-
+- if (!dhdsdio_chipmatch((u16) bus->ci->chip)) {
+- DHD_ERROR(("%s: unsupported chip: 0x%04x\n",
+- __func__, bus->ci->chip));
+- goto fail;
+- }
+-
+- dhdsdio_sdiod_drive_strength_init(bus, dhd_sdiod_drive_strength);
+-
+- /* Get info on the ARM and SOCRAM cores... */
+- if (!DHD_NOPMU(bus)) {
+- bus->armrev = SBCOREREV(bcmsdh_reg_read(bus->sdh,
+- CORE_SB(bus->ci->armcorebase, sbidhigh), 4));
+- bus->orig_ramsize = bus->ci->ramsize;
+- if (!(bus->orig_ramsize)) {
+- DHD_ERROR(("%s: failed to find SOCRAM memory!\n",
+- __func__));
+- goto fail;
+- }
+- bus->ramsize = bus->orig_ramsize;
+- if (dhd_dongle_memsize)
+- dhd_dongle_setmemsize(bus, dhd_dongle_memsize);
+-
+- DHD_ERROR(("DHD: dongle ram size is set to %d(orig %d)\n",
+- bus->ramsize, bus->orig_ramsize));
+- }
+-
+- bus->regs = (void *)bus->ci->buscorebase;
+-
+- /* Set core control so an SDIO reset does a backplane reset */
+- OR_REG(&bus->regs->corecontrol, CC_BPRESEN);
+-
+- bcm_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN);
+-
+- /* Locate an appropriately-aligned portion of hdrbuf */
+- bus->rxhdr = (u8 *) roundup((unsigned long)&bus->hdrbuf[0], DHD_SDALIGN);
+-
+- /* Set the poll and/or interrupt flags */
+- bus->intr = (bool) dhd_intr;
+- bus->poll = (bool) dhd_poll;
+- if (bus->poll)
+- bus->pollrate = 1;
+-
+- return true;
+-
+-fail:
+- return false;
+-}
+-
+-static bool dhdsdio_probe_malloc(dhd_bus_t *bus, void *sdh)
+-{
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- if (bus->dhd->maxctl) {
+- bus->rxblen =
+- roundup((bus->dhd->maxctl + SDPCM_HDRLEN),
+- ALIGNMENT) + DHD_SDALIGN;
+- bus->rxbuf = kmalloc(bus->rxblen, GFP_ATOMIC);
+- if (!(bus->rxbuf)) {
+- DHD_ERROR(("%s: kmalloc of %d-byte rxbuf failed\n",
+- __func__, bus->rxblen));
+- goto fail;
+- }
+- }
+-
+- /* Allocate buffer to receive glomed packet */
+- bus->databuf = kmalloc(MAX_DATA_BUF, GFP_ATOMIC);
+- if (!(bus->databuf)) {
+- DHD_ERROR(("%s: kmalloc of %d-byte databuf failed\n",
+- __func__, MAX_DATA_BUF));
+- /* release rxbuf which was already located as above */
+- if (!bus->rxblen)
+- kfree(bus->rxbuf);
+- goto fail;
+- }
+-
+- /* Align the buffer */
+- if ((unsigned long)bus->databuf % DHD_SDALIGN)
+- bus->dataptr =
+- bus->databuf + (DHD_SDALIGN -
+- ((unsigned long)bus->databuf % DHD_SDALIGN));
+- else
+- bus->dataptr = bus->databuf;
+-
+- return true;
+-
+-fail:
+- return false;
+-}
+-
+-static bool dhdsdio_probe_init(dhd_bus_t *bus, void *sdh)
+-{
+- s32 fnum;
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+-#ifdef SDTEST
+- dhdsdio_pktgen_init(bus);
+-#endif /* SDTEST */
+-
+- /* Disable F2 to clear any intermediate frame state on the dongle */
+- bcmsdh_cfg_write(sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1,
+- NULL);
+-
+- bus->dhd->busstate = DHD_BUS_DOWN;
+- bus->sleeping = false;
+- bus->rxflow = false;
+- bus->prev_rxlim_hit = 0;
+-
+- /* Done with backplane-dependent accesses, can drop clock... */
+- bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
+-
+- /* ...and initialize clock/power states */
+- bus->clkstate = CLK_SDONLY;
+- bus->idletime = (s32) dhd_idletime;
+- bus->idleclock = DHD_IDLE_ACTIVE;
+-
+- /* Query the SD clock speed */
+- if (bcmsdh_iovar_op(sdh, "sd_divisor", NULL, 0,
+- &bus->sd_divisor, sizeof(s32),
+- false) != 0) {
+- DHD_ERROR(("%s: fail on %s get\n", __func__, "sd_divisor"));
+- bus->sd_divisor = -1;
+- } else {
+- DHD_INFO(("%s: Initial value for %s is %d\n",
+- __func__, "sd_divisor", bus->sd_divisor));
+- }
+-
+- /* Query the SD bus mode */
+- if (bcmsdh_iovar_op(sdh, "sd_mode", NULL, 0,
+- &bus->sd_mode, sizeof(s32), false) != 0) {
+- DHD_ERROR(("%s: fail on %s get\n", __func__, "sd_mode"));
+- bus->sd_mode = -1;
+- } else {
+- DHD_INFO(("%s: Initial value for %s is %d\n",
+- __func__, "sd_mode", bus->sd_mode));
+- }
+-
+- /* Query the F2 block size, set roundup accordingly */
+- fnum = 2;
+- if (bcmsdh_iovar_op(sdh, "sd_blocksize", &fnum, sizeof(s32),
+- &bus->blocksize, sizeof(s32), false) != 0) {
+- bus->blocksize = 0;
+- DHD_ERROR(("%s: fail on %s get\n", __func__, "sd_blocksize"));
+- } else {
+- DHD_INFO(("%s: Initial value for %s is %d\n",
+- __func__, "sd_blocksize", bus->blocksize));
+- }
+- bus->roundup = min(max_roundup, bus->blocksize);
+-
+- /* Query if bus module supports packet chaining,
+- default to use if supported */
+- if (bcmsdh_iovar_op(sdh, "sd_rxchain", NULL, 0,
+- &bus->sd_rxchain, sizeof(s32),
+- false) != 0) {
+- bus->sd_rxchain = false;
+- } else {
+- DHD_INFO(("%s: bus module (through bcmsdh API) %s chaining\n",
+- __func__,
+- (bus->sd_rxchain ? "supports" : "does not support")));
+- }
+- bus->use_rxchain = (bool) bus->sd_rxchain;
+-
+- return true;
+-}
+-
+-bool
+-dhd_bus_download_firmware(struct dhd_bus *bus, char *fw_path, char *nv_path)
+-{
+- bool ret;
+- bus->fw_path = fw_path;
+- bus->nv_path = nv_path;
+-
+- ret = dhdsdio_download_firmware(bus, bus->sdh);
+-
+- return ret;
+-}
+-
+-static bool
+-dhdsdio_download_firmware(struct dhd_bus *bus, void *sdh)
+-{
+- bool ret;
+-
+- /* Download the firmware */
+- dhdsdio_clkctl(bus, CLK_AVAIL, false);
+-
+- ret = _dhdsdio_download_firmware(bus) == 0;
+-
+- dhdsdio_clkctl(bus, CLK_SDONLY, false);
+-
+- return ret;
+-}
+-
+-/* Detach and free everything */
+-static void dhdsdio_release(dhd_bus_t *bus)
+-{
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- if (bus) {
+- /* De-register interrupt handler */
+- bcmsdh_intr_disable(bus->sdh);
+- bcmsdh_intr_dereg(bus->sdh);
+-
+- if (bus->dhd) {
+- dhd_detach(bus->dhd);
+- dhdsdio_release_dongle(bus);
+- bus->dhd = NULL;
+- }
+-
+- dhdsdio_release_malloc(bus);
+-
+- kfree(bus);
+- }
+-
+- DHD_TRACE(("%s: Disconnected\n", __func__));
+-}
+-
+-static void dhdsdio_release_malloc(dhd_bus_t *bus)
+-{
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- if (bus->dhd && bus->dhd->dongle_reset)
+- return;
+-
+- if (bus->rxbuf) {
+- kfree(bus->rxbuf);
+- bus->rxctl = bus->rxbuf = NULL;
+- bus->rxlen = 0;
+- }
+-
+- kfree(bus->databuf);
+- bus->databuf = NULL;
+-}
+-
+-static void dhdsdio_release_dongle(dhd_bus_t *bus)
+-{
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- if (bus->dhd && bus->dhd->dongle_reset)
+- return;
+-
+- if (bus->ci) {
+- dhdsdio_clkctl(bus, CLK_AVAIL, false);
+- dhdsdio_clkctl(bus, CLK_NONE, false);
+- dhdsdio_chip_detach(bus);
+- if (bus->vars && bus->varsz)
+- kfree(bus->vars);
+- bus->vars = NULL;
+- }
+-
+- DHD_TRACE(("%s: Disconnected\n", __func__));
+-}
+-
+-static void dhdsdio_disconnect(void *ptr)
+-{
+- dhd_bus_t *bus = (dhd_bus_t *)ptr;
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- if (bus) {
+- ASSERT(bus->dhd);
+- dhdsdio_release(bus);
+- }
+-
+- DHD_TRACE(("%s: Disconnected\n", __func__));
+-}
+-
+-/* Register/Unregister functions are called by the main DHD entry
+- * point (e.g. module insertion) to link with the bus driver, in
+- * order to look for or await the device.
+- */
+-
+-static bcmsdh_driver_t dhd_sdio = {
+- dhdsdio_probe,
+- dhdsdio_disconnect
+-};
+-
+-int dhd_bus_register(void)
+-{
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- return bcmsdh_register(&dhd_sdio);
+-}
+-
+-void dhd_bus_unregister(void)
+-{
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- bcmsdh_unregister();
+-}
+-
+-#ifdef BCMEMBEDIMAGE
+-static int dhdsdio_download_code_array(struct dhd_bus *bus)
+-{
+- int bcmerror = -1;
+- int offset = 0;
+-
+- DHD_INFO(("%s: download embedded firmware...\n", __func__));
+-
+- /* Download image */
+- while ((offset + MEMBLOCK) < sizeof(dlarray)) {
+- bcmerror =
+- dhdsdio_membytes(bus, true, offset, dlarray + offset,
+- MEMBLOCK);
+- if (bcmerror) {
+- DHD_ERROR(("%s: error %d on writing %d membytes at "
+- "0x%08x\n",
+- __func__, bcmerror, MEMBLOCK, offset));
+- goto err;
+- }
+-
+- offset += MEMBLOCK;
+- }
+-
+- if (offset < sizeof(dlarray)) {
+- bcmerror = dhdsdio_membytes(bus, true, offset,
+- dlarray + offset,
+- sizeof(dlarray) - offset);
+- if (bcmerror) {
+- DHD_ERROR(("%s: error %d on writing %d membytes at "
+- "0x%08x\n", __func__, bcmerror,
+- sizeof(dlarray) - offset, offset));
+- goto err;
+- }
+- }
+-#ifdef DHD_DEBUG
+- /* Upload and compare the downloaded code */
+- {
+- unsigned char *ularray;
+-
+- ularray = kmalloc(bus->ramsize, GFP_ATOMIC);
+- if (!ularray) {
+- bcmerror = -ENOMEM;
+- goto err;
+- }
+- /* Upload image to verify downloaded contents. */
+- offset = 0;
+- memset(ularray, 0xaa, bus->ramsize);
+- while ((offset + MEMBLOCK) < sizeof(dlarray)) {
+- bcmerror =
+- dhdsdio_membytes(bus, false, offset,
+- ularray + offset, MEMBLOCK);
+- if (bcmerror) {
+- DHD_ERROR(("%s: error %d on reading %d membytes"
+- " at 0x%08x\n",
+- __func__, bcmerror, MEMBLOCK, offset));
+- goto free;
+- }
+-
+- offset += MEMBLOCK;
+- }
+-
+- if (offset < sizeof(dlarray)) {
+- bcmerror = dhdsdio_membytes(bus, false, offset,
+- ularray + offset,
+- sizeof(dlarray) - offset);
+- if (bcmerror) {
+- DHD_ERROR(("%s: error %d on reading %d membytes at 0x%08x\n",
+- __func__, bcmerror,
+- sizeof(dlarray) - offset, offset));
+- goto free;
+- }
+- }
+-
+- if (memcmp(dlarray, ularray, sizeof(dlarray))) {
+- DHD_ERROR(("%s: Downloaded image is corrupted.\n",
+- __func__));
+- ASSERT(0);
+- goto free;
+- } else
+- DHD_ERROR(("%s: Download/Upload/Compare succeeded.\n",
+- __func__));
+-free:
+- kfree(ularray);
+- }
+-#endif /* DHD_DEBUG */
+-
+-err:
+- return bcmerror;
+-}
+-#endif /* BCMEMBEDIMAGE */
+-
+-static int dhdsdio_download_code_file(struct dhd_bus *bus, char *fw_path)
+-{
+- int bcmerror = -1;
+- int offset = 0;
+- uint len;
+- void *image = NULL;
+- u8 *memblock = NULL, *memptr;
+-
+- DHD_INFO(("%s: download firmware %s\n", __func__, fw_path));
+-
+- image = dhd_os_open_image(fw_path);
+- if (image == NULL)
+- goto err;
+-
+- memptr = memblock = kmalloc(MEMBLOCK + DHD_SDALIGN, GFP_ATOMIC);
+- if (memblock == NULL) {
+- DHD_ERROR(("%s: Failed to allocate memory %d bytes\n",
+- __func__, MEMBLOCK));
+- goto err;
+- }
+- if ((u32)(unsigned long)memblock % DHD_SDALIGN)
+- memptr +=
+- (DHD_SDALIGN - ((u32)(unsigned long)memblock % DHD_SDALIGN));
+-
+- /* Download image */
+- while ((len =
+- dhd_os_get_image_block((char *)memptr, MEMBLOCK, image))) {
+- bcmerror = dhdsdio_membytes(bus, true, offset, memptr, len);
+- if (bcmerror) {
+- DHD_ERROR(("%s: error %d on writing %d membytes at "
+- "0x%08x\n", __func__, bcmerror, MEMBLOCK, offset));
+- goto err;
+- }
+-
+- offset += MEMBLOCK;
+- }
+-
+-err:
+- kfree(memblock);
+-
+- if (image)
+- dhd_os_close_image(image);
+-
+- return bcmerror;
+-}
+-
+-/*
+- * ProcessVars:Takes a buffer of "<var>=<value>\n" lines read from a file
+- * and ending in a NUL.
+- * Removes carriage returns, empty lines, comment lines, and converts
+- * newlines to NULs.
+- * Shortens buffer as needed and pads with NULs. End of buffer is marked
+- * by two NULs.
+-*/
+-
+-static uint process_nvram_vars(char *varbuf, uint len)
+-{
+- char *dp;
+- bool findNewline;
+- int column;
+- uint buf_len, n;
+-
+- dp = varbuf;
+-
+- findNewline = false;
+- column = 0;
+-
+- for (n = 0; n < len; n++) {
+- if (varbuf[n] == 0)
+- break;
+- if (varbuf[n] == '\r')
+- continue;
+- if (findNewline && varbuf[n] != '\n')
+- continue;
+- findNewline = false;
+- if (varbuf[n] == '#') {
+- findNewline = true;
+- continue;
+- }
+- if (varbuf[n] == '\n') {
+- if (column == 0)
+- continue;
+- *dp++ = 0;
+- column = 0;
+- continue;
+- }
+- *dp++ = varbuf[n];
+- column++;
+- }
+- buf_len = dp - varbuf;
+-
+- while (dp < varbuf + n)
+- *dp++ = 0;
+-
+- return buf_len;
+-}
+-
+-/*
+- EXAMPLE: nvram_array
+- nvram_arry format:
+- name=value
+- Use carriage return at the end of each assignment,
+- and an empty string with
+- carriage return at the end of array.
+-
+- For example:
+- unsigned char nvram_array[] = {"name1=value1\n",
+- "name2=value2\n", "\n"};
+- Hex values start with 0x, and mac addr format: xx:xx:xx:xx:xx:xx.
+-
+- Search "EXAMPLE: nvram_array" to see how the array is activated.
+-*/
+-
+-void dhd_bus_set_nvram_params(struct dhd_bus *bus, const char *nvram_params)
+-{
+- bus->nvram_params = nvram_params;
+-}
+-
+-static int dhdsdio_download_nvram(struct dhd_bus *bus)
+-{
+- int bcmerror = -1;
+- uint len;
+- void *image = NULL;
+- char *memblock = NULL;
+- char *bufp;
+- char *nv_path;
+- bool nvram_file_exists;
+-
+- nv_path = bus->nv_path;
+-
+- nvram_file_exists = ((nv_path != NULL) && (nv_path[0] != '\0'));
+- if (!nvram_file_exists && (bus->nvram_params == NULL))
+- return 0;
+-
+- if (nvram_file_exists) {
+- image = dhd_os_open_image(nv_path);
+- if (image == NULL)
+- goto err;
+- }
+-
+- memblock = kmalloc(MEMBLOCK, GFP_ATOMIC);
+- if (memblock == NULL) {
+- DHD_ERROR(("%s: Failed to allocate memory %d bytes\n",
+- __func__, MEMBLOCK));
+- goto err;
+- }
+-
+- /* Download variables */
+- if (nvram_file_exists) {
+- len = dhd_os_get_image_block(memblock, MEMBLOCK, image);
+- } else {
+- len = strlen(bus->nvram_params);
+- ASSERT(len <= MEMBLOCK);
+- if (len > MEMBLOCK)
+- len = MEMBLOCK;
+- memcpy(memblock, bus->nvram_params, len);
+- }
+-
+- if (len > 0 && len < MEMBLOCK) {
+- bufp = (char *)memblock;
+- bufp[len] = 0;
+- len = process_nvram_vars(bufp, len);
+- bufp += len;
+- *bufp++ = 0;
+- if (len)
+- bcmerror = dhdsdio_downloadvars(bus, memblock, len + 1);
+- if (bcmerror) {
+- DHD_ERROR(("%s: error downloading vars: %d\n",
+- __func__, bcmerror));
+- }
+- } else {
+- DHD_ERROR(("%s: error reading nvram file: %d\n",
+- __func__, len));
+- bcmerror = -EIO;
+- }
+-
+-err:
+- kfree(memblock);
+-
+- if (image)
+- dhd_os_close_image(image);
+-
+- return bcmerror;
+-}
+-
+-static int _dhdsdio_download_firmware(struct dhd_bus *bus)
+-{
+- int bcmerror = -1;
+-
+- bool embed = false; /* download embedded firmware */
+- bool dlok = false; /* download firmware succeeded */
+-
+- /* Out immediately if no image to download */
+- if ((bus->fw_path == NULL) || (bus->fw_path[0] == '\0')) {
+-#ifdef BCMEMBEDIMAGE
+- embed = true;
+-#else
+- return bcmerror;
+-#endif
+- }
+-
+- /* Keep arm in reset */
+- if (dhdsdio_download_state(bus, true)) {
+- DHD_ERROR(("%s: error placing ARM core in reset\n", __func__));
+- goto err;
+- }
+-
+- /* External image takes precedence if specified */
+- if ((bus->fw_path != NULL) && (bus->fw_path[0] != '\0')) {
+- if (dhdsdio_download_code_file(bus, bus->fw_path)) {
+- DHD_ERROR(("%s: dongle image file download failed\n",
+- __func__));
+-#ifdef BCMEMBEDIMAGE
+- embed = true;
+-#else
+- goto err;
+-#endif
+- } else {
+- embed = false;
+- dlok = true;
+- }
+- }
+-#ifdef BCMEMBEDIMAGE
+- if (embed) {
+- if (dhdsdio_download_code_array(bus)) {
+- DHD_ERROR(("%s: dongle image array download failed\n",
+- __func__));
+- goto err;
+- } else {
+- dlok = true;
+- }
+- }
+-#endif
+- if (!dlok) {
+- DHD_ERROR(("%s: dongle image download failed\n", __func__));
+- goto err;
+- }
+-
+- /* EXAMPLE: nvram_array */
+- /* If a valid nvram_arry is specified as above, it can be passed
+- down to dongle */
+- /* dhd_bus_set_nvram_params(bus, (char *)&nvram_array); */
+-
+- /* External nvram takes precedence if specified */
+- if (dhdsdio_download_nvram(bus)) {
+- DHD_ERROR(("%s: dongle nvram file download failed\n",
+- __func__));
+- }
+-
+- /* Take arm out of reset */
+- if (dhdsdio_download_state(bus, false)) {
+- DHD_ERROR(("%s: error getting out of ARM core reset\n",
+- __func__));
+- goto err;
+- }
+-
+- bcmerror = 0;
+-
+-err:
+- return bcmerror;
+-}
+-
+-
+-static int
+-dhd_bcmsdh_send_buf(dhd_bus_t *bus, u32 addr, uint fn, uint flags,
+- u8 *buf, uint nbytes, struct sk_buff *pkt,
+- bcmsdh_cmplt_fn_t complete, void *handle)
+-{
+- return bcmsdh_send_buf
+- (bus->sdh, addr, fn, flags, buf, nbytes, pkt, complete,
+- handle);
+-}
+-
+-uint dhd_bus_chip(struct dhd_bus *bus)
+-{
+- ASSERT(bus->ci != NULL);
+- return bus->ci->chip;
+-}
+-
+-void *dhd_bus_pub(struct dhd_bus *bus)
+-{
+- return bus->dhd;
+-}
+-
+-void *dhd_bus_txq(struct dhd_bus *bus)
+-{
+- return &bus->txq;
+-}
+-
+-uint dhd_bus_hdrlen(struct dhd_bus *bus)
+-{
+- return SDPCM_HDRLEN;
+-}
+-
+-int dhd_bus_devreset(dhd_pub_t *dhdp, u8 flag)
+-{
+- int bcmerror = 0;
+- dhd_bus_t *bus;
+-
+- bus = dhdp->bus;
+-
+- if (flag == true) {
+- if (!bus->dhd->dongle_reset) {
+- /* Expect app to have torn down any
+- connection before calling */
+- /* Stop the bus, disable F2 */
+- dhd_bus_stop(bus, false);
+-
+- /* Clean tx/rx buffer pointers,
+- detach from the dongle */
+- dhdsdio_release_dongle(bus);
+-
+- bus->dhd->dongle_reset = true;
+- bus->dhd->up = false;
+-
+- DHD_TRACE(("%s: WLAN OFF DONE\n", __func__));
+- /* App can now remove power from device */
+- } else
+- bcmerror = -EIO;
+- } else {
+- /* App must have restored power to device before calling */
+-
+- DHD_TRACE(("\n\n%s: == WLAN ON ==\n", __func__));
+-
+- if (bus->dhd->dongle_reset) {
+- /* Turn on WLAN */
+- /* Reset SD client */
+- bcmsdh_reset(bus->sdh);
+-
+- /* Attempt to re-attach & download */
+- if (dhdsdio_probe_attach(bus, bus->sdh,
+- (u32 *) SI_ENUM_BASE,
+- bus->cl_devid)) {
+- /* Attempt to download binary to the dongle */
+- if (dhdsdio_probe_init
+- (bus, bus->sdh)
+- && dhdsdio_download_firmware(bus,
+- bus->sdh)) {
+-
+- /* Re-init bus, enable F2 transfer */
+- dhd_bus_init((dhd_pub_t *) bus->dhd,
+- false);
+-
+-#if defined(OOB_INTR_ONLY)
+- dhd_enable_oob_intr(bus, true);
+-#endif /* defined(OOB_INTR_ONLY) */
+-
+- bus->dhd->dongle_reset = false;
+- bus->dhd->up = true;
+-
+- DHD_TRACE(("%s: WLAN ON DONE\n",
+- __func__));
+- } else
+- bcmerror = -EIO;
+- } else
+- bcmerror = -EIO;
+- } else {
+- bcmerror = -EISCONN;
+- DHD_ERROR(("%s: Set DEVRESET=false invoked when device "
+- "is on\n", __func__));
+- bcmerror = -EIO;
+- }
+- }
+- return bcmerror;
+-}
+-
+-static int
+-dhdsdio_chip_recognition(bcmsdh_info_t *sdh, struct chip_info *ci, void *regs)
+-{
+- u32 regdata;
+-
+- /*
+- * Get CC core rev
+- * Chipid is assume to be at offset 0 from regs arg
+- * For different chiptypes or old sdio hosts w/o chipcommon,
+- * other ways of recognition should be added here.
+- */
+- ci->cccorebase = (u32)regs;
+- regdata = bcmsdh_reg_read(sdh, CORE_CC_REG(ci->cccorebase, chipid), 4);
+- ci->chip = regdata & CID_ID_MASK;
+- ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT;
+-
+- DHD_INFO(("%s: chipid=0x%x chiprev=%d\n",
+- __func__, ci->chip, ci->chiprev));
+-
+- /* Address of cores for new chips should be added here */
+- switch (ci->chip) {
+- case BCM4329_CHIP_ID:
+- ci->buscorebase = BCM4329_CORE_BUS_BASE;
+- ci->ramcorebase = BCM4329_CORE_SOCRAM_BASE;
+- ci->armcorebase = BCM4329_CORE_ARM_BASE;
+- ci->ramsize = BCM4329_RAMSIZE;
+- break;
+- default:
+- DHD_ERROR(("%s: chipid 0x%x is not supported\n",
+- __func__, ci->chip));
+- return -ENODEV;
+- }
+-
+- regdata = bcmsdh_reg_read(sdh,
+- CORE_SB(ci->cccorebase, sbidhigh), 4);
+- ci->ccrev = SBCOREREV(regdata);
+-
+- regdata = bcmsdh_reg_read(sdh,
+- CORE_CC_REG(ci->cccorebase, pmucapabilities), 4);
+- ci->pmurev = regdata & PCAP_REV_MASK;
+-
+- regdata = bcmsdh_reg_read(sdh, CORE_SB(ci->buscorebase, sbidhigh), 4);
+- ci->buscorerev = SBCOREREV(regdata);
+- ci->buscoretype = (regdata & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT;
+-
+- DHD_INFO(("%s: ccrev=%d, pmurev=%d, buscore rev/type=%d/0x%x\n",
+- __func__, ci->ccrev, ci->pmurev,
+- ci->buscorerev, ci->buscoretype));
+-
+- /* get chipcommon capabilites */
+- ci->cccaps = bcmsdh_reg_read(sdh,
+- CORE_CC_REG(ci->cccorebase, capabilities), 4);
+-
+- return 0;
+-}
+-
+-static void
+-dhdsdio_chip_disablecore(bcmsdh_info_t *sdh, u32 corebase)
+-{
+- u32 regdata;
+-
+- regdata = bcmsdh_reg_read(sdh,
+- CORE_SB(corebase, sbtmstatelow), 4);
+- if (regdata & SBTML_RESET)
+- return;
+-
+- regdata = bcmsdh_reg_read(sdh,
+- CORE_SB(corebase, sbtmstatelow), 4);
+- if ((regdata & (SICF_CLOCK_EN << SBTML_SICF_SHIFT)) != 0) {
+- /*
+- * set target reject and spin until busy is clear
+- * (preserve core-specific bits)
+- */
+- regdata = bcmsdh_reg_read(sdh,
+- CORE_SB(corebase, sbtmstatelow), 4);
+- bcmsdh_reg_write(sdh, CORE_SB(corebase, sbtmstatelow), 4,
+- regdata | SBTML_REJ);
+-
+- regdata = bcmsdh_reg_read(sdh,
+- CORE_SB(corebase, sbtmstatelow), 4);
+- udelay(1);
+- SPINWAIT((bcmsdh_reg_read(sdh,
+- CORE_SB(corebase, sbtmstatehigh), 4) &
+- SBTMH_BUSY), 100000);
+-
+- regdata = bcmsdh_reg_read(sdh,
+- CORE_SB(corebase, sbtmstatehigh), 4);
+- if (regdata & SBTMH_BUSY)
+- DHD_ERROR(("%s: ARM core still busy\n", __func__));
+-
+- regdata = bcmsdh_reg_read(sdh,
+- CORE_SB(corebase, sbidlow), 4);
+- if (regdata & SBIDL_INIT) {
+- regdata = bcmsdh_reg_read(sdh,
+- CORE_SB(corebase, sbimstate), 4) |
+- SBIM_RJ;
+- bcmsdh_reg_write(sdh,
+- CORE_SB(corebase, sbimstate), 4,
+- regdata);
+- regdata = bcmsdh_reg_read(sdh,
+- CORE_SB(corebase, sbimstate), 4);
+- udelay(1);
+- SPINWAIT((bcmsdh_reg_read(sdh,
+- CORE_SB(corebase, sbimstate), 4) &
+- SBIM_BY), 100000);
+- }
+-
+- /* set reset and reject while enabling the clocks */
+- bcmsdh_reg_write(sdh,
+- CORE_SB(corebase, sbtmstatelow), 4,
+- (((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) |
+- SBTML_REJ | SBTML_RESET));
+- regdata = bcmsdh_reg_read(sdh,
+- CORE_SB(corebase, sbtmstatelow), 4);
+- udelay(10);
+-
+- /* clear the initiator reject bit */
+- regdata = bcmsdh_reg_read(sdh,
+- CORE_SB(corebase, sbidlow), 4);
+- if (regdata & SBIDL_INIT) {
+- regdata = bcmsdh_reg_read(sdh,
+- CORE_SB(corebase, sbimstate), 4) &
+- ~SBIM_RJ;
+- bcmsdh_reg_write(sdh,
+- CORE_SB(corebase, sbimstate), 4,
+- regdata);
+- }
+- }
+-
+- /* leave reset and reject asserted */
+- bcmsdh_reg_write(sdh, CORE_SB(corebase, sbtmstatelow), 4,
+- (SBTML_REJ | SBTML_RESET));
+- udelay(1);
+-}
+-
+-static int
+-dhdsdio_chip_attach(struct dhd_bus *bus, void *regs)
+-{
+- struct chip_info *ci;
+- int err;
+- u8 clkval, clkset;
+-
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- /* alloc chip_info_t */
+- ci = kmalloc(sizeof(struct chip_info), GFP_ATOMIC);
+- if (NULL == ci) {
+- DHD_ERROR(("%s: malloc failed!\n", __func__));
+- return -ENOMEM;
+- }
+-
+- memset((unsigned char *)ci, 0, sizeof(struct chip_info));
+-
+- /* bus/core/clk setup for register access */
+- /* Try forcing SDIO core to do ALPAvail request only */
+- clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
+- bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
+- clkset, &err);
+- if (err) {
+- DHD_ERROR(("%s: error writing for HT off\n", __func__));
+- goto fail;
+- }
+-
+- /* If register supported, wait for ALPAvail and then force ALP */
+- /* This may take up to 15 milliseconds */
+- clkval = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
+- SBSDIO_FUNC1_CHIPCLKCSR, NULL);
+- if ((clkval & ~SBSDIO_AVBITS) == clkset) {
+- SPINWAIT(((clkval =
+- bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
+- SBSDIO_FUNC1_CHIPCLKCSR,
+- NULL)),
+- !SBSDIO_ALPAV(clkval)),
+- PMU_MAX_TRANSITION_DLY);
+- if (!SBSDIO_ALPAV(clkval)) {
+- DHD_ERROR(("%s: timeout on ALPAV wait, clkval 0x%02x\n",
+- __func__, clkval));
+- err = -EBUSY;
+- goto fail;
+- }
+- clkset = SBSDIO_FORCE_HW_CLKREQ_OFF |
+- SBSDIO_FORCE_ALP;
+- bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1,
+- SBSDIO_FUNC1_CHIPCLKCSR,
+- clkset, &err);
+- udelay(65);
+- } else {
+- DHD_ERROR(("%s: ChipClkCSR access: wrote 0x%02x read 0x%02x\n",
+- __func__, clkset, clkval));
+- err = -EACCES;
+- goto fail;
+- }
+-
+- /* Also, disable the extra SDIO pull-ups */
+- bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SDIOPULLUP, 0,
+- NULL);
+-
+- err = dhdsdio_chip_recognition(bus->sdh, ci, regs);
+- if (err)
+- goto fail;
+-
+- /*
+- * Make sure any on-chip ARM is off (in case strapping is wrong),
+- * or downloaded code was already running.
+- */
+- dhdsdio_chip_disablecore(bus->sdh, ci->armcorebase);
+-
+- bcmsdh_reg_write(bus->sdh,
+- CORE_CC_REG(ci->cccorebase, gpiopullup), 4, 0);
+- bcmsdh_reg_write(bus->sdh,
+- CORE_CC_REG(ci->cccorebase, gpiopulldown), 4, 0);
+-
+- /* Disable F2 to clear any intermediate frame state on the dongle */
+- bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN,
+- SDIO_FUNC_ENABLE_1, NULL);
+-
+- /* WAR: cmd52 backplane read so core HW will drop ALPReq */
+- clkval = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
+- 0, NULL);
+-
+- /* Done with backplane-dependent accesses, can drop clock... */
+- bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0,
+- NULL);
+-
+- bus->ci = ci;
+- return 0;
+-fail:
+- bus->ci = NULL;
+- kfree(ci);
+- return err;
+-}
+-
+-static void
+-dhdsdio_chip_resetcore(bcmsdh_info_t *sdh, u32 corebase)
+-{
+- u32 regdata;
+-
+- /*
+- * Must do the disable sequence first to work for
+- * arbitrary current core state.
+- */
+- dhdsdio_chip_disablecore(sdh, corebase);
+-
+- /*
+- * Now do the initialization sequence.
+- * set reset while enabling the clock and
+- * forcing them on throughout the core
+- */
+- bcmsdh_reg_write(sdh, CORE_SB(corebase, sbtmstatelow), 4,
+- ((SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) |
+- SBTML_RESET);
+- udelay(1);
+-
+- regdata = bcmsdh_reg_read(sdh, CORE_SB(corebase, sbtmstatehigh), 4);
+- if (regdata & SBTMH_SERR)
+- bcmsdh_reg_write(sdh, CORE_SB(corebase, sbtmstatehigh), 4, 0);
+-
+- regdata = bcmsdh_reg_read(sdh, CORE_SB(corebase, sbimstate), 4);
+- if (regdata & (SBIM_IBE | SBIM_TO))
+- bcmsdh_reg_write(sdh, CORE_SB(corebase, sbimstate), 4,
+- regdata & ~(SBIM_IBE | SBIM_TO));
+-
+- /* clear reset and allow it to propagate throughout the core */
+- bcmsdh_reg_write(sdh, CORE_SB(corebase, sbtmstatelow), 4,
+- (SICF_FGC << SBTML_SICF_SHIFT) |
+- (SICF_CLOCK_EN << SBTML_SICF_SHIFT));
+- udelay(1);
+-
+- /* leave clock enabled */
+- bcmsdh_reg_write(sdh, CORE_SB(corebase, sbtmstatelow), 4,
+- (SICF_CLOCK_EN << SBTML_SICF_SHIFT));
+- udelay(1);
+-}
+-
+-/* SDIO Pad drive strength to select value mappings */
+-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}
+- };
+-
+-#define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu))
+-
+-static void
+-dhdsdio_sdiod_drive_strength_init(struct dhd_bus *bus, u32 drivestrength) {
+- struct sdiod_drive_str *str_tab = NULL;
+- u32 str_mask = 0;
+- u32 str_shift = 0;
+- char chn[8];
+-
+- if (!(bus->ci->cccaps & CC_CAP_PMU))
+- return;
+-
+- switch (SDIOD_DRVSTR_KEY(bus->ci->chip, bus->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;
+- str_mask = 0x00003800;
+- str_shift = 11;
+- break;
+- default:
+- DHD_ERROR(("No SDIO Drive strength init"
+- "done for chip %s rev %d pmurev %d\n",
+- bcm_chipname(bus->ci->chip, chn, 8),
+- bus->ci->chiprev, bus->ci->pmurev));
+- break;
+- }
+-
+- if (str_tab != NULL) {
+- u32 drivestrength_sel = 0;
+- u32 cc_data_temp;
+- int i;
+-
+- for (i = 0; str_tab[i].strength != 0; i++) {
+- if (drivestrength >= str_tab[i].strength) {
+- drivestrength_sel = str_tab[i].sel;
+- break;
+- }
+- }
+-
+- bcmsdh_reg_write(bus->sdh,
+- CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr),
+- 4, 1);
+- cc_data_temp = bcmsdh_reg_read(bus->sdh,
+- CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr), 4);
+- cc_data_temp &= ~str_mask;
+- drivestrength_sel <<= str_shift;
+- cc_data_temp |= drivestrength_sel;
+- bcmsdh_reg_write(bus->sdh,
+- CORE_CC_REG(bus->ci->cccorebase, chipcontrol_addr),
+- 4, cc_data_temp);
+-
+- DHD_INFO(("SDIO: %dmA drive strength selected, set to 0x%08x\n",
+- drivestrength, cc_data_temp));
+- }
+-}
+-
+-static void
+-dhdsdio_chip_detach(struct dhd_bus *bus)
+-{
+- DHD_TRACE(("%s: Enter\n", __func__));
+-
+- kfree(bus->ci);
+- bus->ci = NULL;
+-}
+diff --git a/drivers/staging/brcm80211/brcmfmac/dhdioctl.h b/drivers/staging/brcm80211/brcmfmac/dhdioctl.h
+deleted file mode 100644
+index f0ba535..0000000
+--- a/drivers/staging/brcm80211/brcmfmac/dhdioctl.h
++++ /dev/null
+@@ -1,100 +0,0 @@
+-/*
+- * Copyright (c) 2010 Broadcom Corporation
+- *
+- * 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 _dhdioctl_h_
+-#define _dhdioctl_h_
+-
+-/* Linux network driver ioctl encoding */
+-typedef struct dhd_ioctl {
+- uint cmd; /* common ioctl definition */
+- void *buf; /* pointer to user buffer */
+- uint len; /* length of user buffer */
+- bool set; /* get or set request (optional) */
+- uint used; /* bytes read or written (optional) */
+- uint needed; /* bytes needed (optional) */
+- uint driver; /* to identify target driver */
+-} dhd_ioctl_t;
+-
+-/* per-driver magic numbers */
+-#define DHD_IOCTL_MAGIC 0x00444944
+-
+-/* bump this number if you change the ioctl interface */
+-#define DHD_IOCTL_VERSION 1
+-
+-#define DHD_IOCTL_MAXLEN 8192 /* max length ioctl buffer required */
+-#define DHD_IOCTL_SMLEN 256 /* "small" length ioctl buffer required */
+-
+-/* common ioctl definitions */
+-#define DHD_GET_MAGIC 0
+-#define DHD_GET_VERSION 1
+-#define DHD_GET_VAR 2
+-#define DHD_SET_VAR 3
+-
+-/* message levels */
+-#define DHD_ERROR_VAL 0x0001
+-#define DHD_TRACE_VAL 0x0002
+-#define DHD_INFO_VAL 0x0004
+-#define DHD_DATA_VAL 0x0008
+-#define DHD_CTL_VAL 0x0010
+-#define DHD_TIMER_VAL 0x0020
+-#define DHD_HDRS_VAL 0x0040
+-#define DHD_BYTES_VAL 0x0080
+-#define DHD_INTR_VAL 0x0100
+-#define DHD_LOG_VAL 0x0200
+-#define DHD_GLOM_VAL 0x0400
+-#define DHD_EVENT_VAL 0x0800
+-#define DHD_BTA_VAL 0x1000
+-#define DHD_ISCAN_VAL 0x2000
+-
+-#ifdef SDTEST
+-/* For pktgen iovar */
+-typedef struct dhd_pktgen {
+- uint version; /* To allow structure change tracking */
+- uint freq; /* Max ticks between tx/rx attempts */
+- uint count; /* Test packets to send/rcv each attempt */
+- uint print; /* Print counts every <print> attempts */
+- uint total; /* Total packets (or bursts) */
+- uint minlen; /* Minimum length of packets to send */
+- uint maxlen; /* Maximum length of packets to send */
+- uint numsent; /* Count of test packets sent */
+- uint numrcvd; /* Count of test packets received */
+- uint numfail; /* Count of test send failures */
+- uint mode; /* Test mode (type of test packets) */
+- uint stop; /* Stop after this many tx failures */
+-} dhd_pktgen_t;
+-
+-/* Version in case structure changes */
+-#define DHD_PKTGEN_VERSION 2
+-
+-/* Type of test packets to use */
+-#define DHD_PKTGEN_ECHO 1 /* Send echo requests */
+-#define DHD_PKTGEN_SEND 2 /* Send discard packets */
+-#define DHD_PKTGEN_RXBURST 3 /* Request dongle send N packets */
+-#define DHD_PKTGEN_RECV 4 /* Continuous rx from continuous
+- tx dongle */
+-#endif /* SDTEST */
+-
+-/* Enter idle immediately (no timeout) */
+-#define DHD_IDLE_IMMEDIATE (-1)
+-
+-/* Values for idleclock iovar: other values are the sd_divisor to use
+- when idle */
+-#define DHD_IDLE_ACTIVE 0 /* Do not request any SD clock change
+- when idle */
+-#define DHD_IDLE_STOP (-1) /* Request SD clock be stopped
+- (and use SD1 mode) */
+-
+-#endif /* _dhdioctl_h_ */
+diff --git a/drivers/staging/brcm80211/brcmfmac/dngl_stats.h b/drivers/staging/brcm80211/brcmfmac/dngl_stats.h
+deleted file mode 100644
+index 699cbff..0000000
+--- a/drivers/staging/brcm80211/brcmfmac/dngl_stats.h
++++ /dev/null
+@@ -1,32 +0,0 @@
+-/*
+- * Copyright (c) 2010 Broadcom Corporation
+- *
+- * 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 _dngl_stats_h_
+-#define _dngl_stats_h_
+-
+-typedef struct {
+- unsigned long rx_packets; /* total packets received */
+- unsigned long tx_packets; /* total packets transmitted */
+- unsigned long rx_bytes; /* total bytes received */
+- unsigned long tx_bytes; /* total bytes transmitted */
+- unsigned long rx_errors; /* bad packets received */
+- unsigned long tx_errors; /* packet transmit problems */
+- unsigned long rx_dropped; /* packets dropped by dongle */
+- unsigned long tx_dropped; /* packets dropped by dongle */
+- unsigned long multicast; /* multicast packets received */
+-} dngl_stats_t;
+-
+-#endif /* _dngl_stats_h_ */
+diff --git a/drivers/staging/brcm80211/brcmfmac/hndrte_armtrap.h b/drivers/staging/brcm80211/brcmfmac/hndrte_armtrap.h
+deleted file mode 100644
+index 28f092c..0000000
+--- a/drivers/staging/brcm80211/brcmfmac/hndrte_armtrap.h
++++ /dev/null
+@@ -1,75 +0,0 @@
+-/*
+- * Copyright (c) 2010 Broadcom Corporation
+- *
+- * 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 _hndrte_armtrap_h
+-#define _hndrte_armtrap_h
+-
+-/* ARM trap handling */
+-
+-/* Trap types defined by ARM (see arminc.h) */
+-
+-/* Trap locations in lo memory */
+-#define TRAP_STRIDE 4
+-#define FIRST_TRAP TR_RST
+-#define LAST_TRAP (TR_FIQ * TRAP_STRIDE)
+-
+-#if defined(__ARM_ARCH_4T__)
+-#define MAX_TRAP_TYPE (TR_FIQ + 1)
+-#elif defined(__ARM_ARCH_7M__)
+-#define MAX_TRAP_TYPE (TR_ISR + ARMCM3_NUMINTS)
+-#endif /* __ARM_ARCH_7M__ */
+-
+-/* The trap structure is defined here as offsets for assembly */
+-#define TR_TYPE 0x00
+-#define TR_EPC 0x04
+-#define TR_CPSR 0x08
+-#define TR_SPSR 0x0c
+-#define TR_REGS 0x10
+-#define TR_REG(n) (TR_REGS + (n) * 4)
+-#define TR_SP TR_REG(13)
+-#define TR_LR TR_REG(14)
+-#define TR_PC TR_REG(15)
+-
+-#define TRAP_T_SIZE 80
+-
+-#ifndef _LANGUAGE_ASSEMBLY
+-
+-typedef struct _trap_struct {
+- u32 type;
+- u32 epc;
+- u32 cpsr;
+- u32 spsr;
+- u32 r0;
+- u32 r1;
+- u32 r2;
+- u32 r3;
+- u32 r4;
+- u32 r5;
+- u32 r6;
+- u32 r7;
+- u32 r8;
+- u32 r9;
+- u32 r10;
+- u32 r11;
+- u32 r12;
+- u32 r13;
+- u32 r14;
+- u32 pc;
+-} trap_t;
+-
+-#endif /* !_LANGUAGE_ASSEMBLY */
+-
+-#endif /* _hndrte_armtrap_h */
+diff --git a/drivers/staging/brcm80211/brcmfmac/hndrte_cons.h b/drivers/staging/brcm80211/brcmfmac/hndrte_cons.h
+deleted file mode 100644
+index 4df3eec..0000000
+--- a/drivers/staging/brcm80211/brcmfmac/hndrte_cons.h
++++ /dev/null
+@@ -1,62 +0,0 @@
+-/*
+- * Copyright (c) 2010 Broadcom Corporation
+- *
+- * 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 _hndrte_cons_h
+-#define _hndrte_cons_h
+-
+-#define CBUF_LEN (128)
+-
+-#define LOG_BUF_LEN 1024
+-
+-typedef struct {
+- u32 buf; /* Can't be pointer on (64-bit) hosts */
+- uint buf_size;
+- uint idx;
+- char *_buf_compat; /* Redundant pointer for backward compat. */
+-} hndrte_log_t;
+-
+-typedef struct {
+- /* Virtual UART
+- * When there is no UART (e.g. Quickturn),
+- * the host should write a complete
+- * input line directly into cbuf and then write
+- * the length into vcons_in.
+- * This may also be used when there is a real UART
+- * (at risk of conflicting with
+- * the real UART). vcons_out is currently unused.
+- */
+- volatile uint vcons_in;
+- volatile uint vcons_out;
+-
+- /* Output (logging) buffer
+- * Console output is written to a ring buffer log_buf at index log_idx.
+- * The host may read the output when it sees log_idx advance.
+- * Output will be lost if the output wraps around faster than the host
+- * polls.
+- */
+- hndrte_log_t log;
+-
+- /* Console input line buffer
+- * Characters are read one at a time into cbuf
+- * until <CR> is received, then
+- * the buffer is processed as a command line.
+- * Also used for virtual UART.
+- */
+- uint cbuf_idx;
+- char cbuf[CBUF_LEN];
+-} hndrte_cons_t;
+-
+-#endif /* _hndrte_cons_h */
+-
+diff --git a/drivers/staging/brcm80211/brcmfmac/msgtrace.h b/drivers/staging/brcm80211/brcmfmac/msgtrace.h
+deleted file mode 100644
+index d654671..0000000
+--- a/drivers/staging/brcm80211/brcmfmac/msgtrace.h
++++ /dev/null
+@@ -1,61 +0,0 @@
+-/*
+- * Copyright (c) 2010 Broadcom Corporation
+- *
+- * 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 _MSGTRACE_H
+-#define _MSGTRACE_H
+-
+-#define MSGTRACE_VERSION 1
+-
+-/* Message trace header */
+-typedef struct msgtrace_hdr {
+- u8 version;
+- u8 spare;
+- u16 len; /* Len of the trace */
+- u32 seqnum; /* Sequence number of message. Useful
+- * if the messsage has been lost
+- * because of DMA error or a bus reset
+- * (ex: SDIO Func2)
+- */
+- u32 discarded_bytes; /* Number of discarded bytes because of
+- trace overflow */
+- u32 discarded_printf; /* Number of discarded printf
+- because of trace overflow */
+-} __attribute__((packed)) msgtrace_hdr_t;
+-
+-#define MSGTRACE_HDRLEN sizeof(msgtrace_hdr_t)
+-
+-/* The hbus driver generates traces when sending a trace message.
+- * This causes endless traces.
+- * This flag must be set to true in any hbus traces.
+- * The flag is reset in the function msgtrace_put.
+- * This prevents endless traces but generates hasardous
+- * lost of traces only in bus device code.
+- * It is recommendat to set this flag in macro SD_TRACE
+- * but not in SD_ERROR for avoiding missing
+- * hbus error traces. hbus error trace should not generates endless traces.
+- */
+-extern bool msgtrace_hbus_trace;
+-
+-typedef void (*msgtrace_func_send_t) (void *hdl1, void *hdl2, u8 *hdr,
+- u16 hdrlen, u8 *buf,
+- u16 buflen);
+-
+-extern void msgtrace_sent(void);
+-extern void msgtrace_put(char *buf, int count);
+-extern void msgtrace_init(void *hdl1, void *hdl2,
+- msgtrace_func_send_t func_send);
+-
+-#endif /* _MSGTRACE_H */
+diff --git a/drivers/staging/brcm80211/brcmfmac/sdioh.h b/drivers/staging/brcm80211/brcmfmac/sdioh.h
+deleted file mode 100644
+index f96aaf9..0000000
+--- a/drivers/staging/brcm80211/brcmfmac/sdioh.h
++++ /dev/null
+@@ -1,63 +0,0 @@
+-/*
+- * Copyright (c) 2010 Broadcom Corporation
+- *
+- * 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 _SDIOH_H
+-#define _SDIOH_H
+-
+-#define SD_SysAddr 0x000
+-#define SD_BlockSize 0x004
+-#define SD_BlockCount 0x006
+-#define SD_Arg0 0x008
+-#define SD_Arg1 0x00A
+-#define SD_TransferMode 0x00C
+-#define SD_Command 0x00E
+-#define SD_Response0 0x010
+-#define SD_Response1 0x012
+-#define SD_Response2 0x014
+-#define SD_Response3 0x016
+-#define SD_Response4 0x018
+-#define SD_Response5 0x01A
+-#define SD_Response6 0x01C
+-#define SD_Response7 0x01E
+-#define SD_BufferDataPort0 0x020
+-#define SD_BufferDataPort1 0x022
+-#define SD_PresentState 0x024
+-#define SD_HostCntrl 0x028
+-#define SD_PwrCntrl 0x029
+-#define SD_BlockGapCntrl 0x02A
+-#define SD_WakeupCntrl 0x02B
+-#define SD_ClockCntrl 0x02C
+-#define SD_TimeoutCntrl 0x02E
+-#define SD_SoftwareReset 0x02F
+-#define SD_IntrStatus 0x030
+-#define SD_ErrorIntrStatus 0x032
+-#define SD_IntrStatusEnable 0x034
+-#define SD_ErrorIntrStatusEnable 0x036
+-#define SD_IntrSignalEnable 0x038
+-#define SD_ErrorIntrSignalEnable 0x03A
+-#define SD_CMD12ErrorStatus 0x03C
+-#define SD_Capabilities 0x040
+-#define SD_Capabilities_Reserved 0x044
+-#define SD_MaxCurCap 0x048
+-#define SD_MaxCurCap_Reserved 0x04C
+-#define SD_ADMA_SysAddr 0x58
+-#define SD_SlotInterruptStatus 0x0FC
+-#define SD_HostControllerVersion 0x0FE
+-
+-/* SD specific registers in PCI config space */
+-#define SD_SlotInfo 0x40
+-
+-#endif /* _SDIOH_H */
+diff --git a/drivers/staging/brcm80211/brcmfmac/sdiovar.h b/drivers/staging/brcm80211/brcmfmac/sdiovar.h
+deleted file mode 100644
+index d1cfa5f..0000000
+--- a/drivers/staging/brcm80211/brcmfmac/sdiovar.h
++++ /dev/null
+@@ -1,38 +0,0 @@
+-/*
+- * Copyright (c) 2010 Broadcom Corporation
+- *
+- * 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 _sdiovar_h_
+-#define _sdiovar_h_
+-
+-typedef struct sdreg {
+- int func;
+- int offset;
+- int value;
+-} sdreg_t;
+-
+-/* Common msglevel constants */
+-#define SDH_ERROR_VAL 0x0001 /* Error */
+-#define SDH_TRACE_VAL 0x0002 /* Trace */
+-#define SDH_INFO_VAL 0x0004 /* Info */
+-#define SDH_DEBUG_VAL 0x0008 /* Debug */
+-#define SDH_DATA_VAL 0x0010 /* Data */
+-#define SDH_CTRL_VAL 0x0020 /* Control Regs */
+-#define SDH_LOG_VAL 0x0040 /* Enable bcmlog */
+-#define SDH_DMA_VAL 0x0080 /* DMA */
+-
+-#define NUM_PREV_TRANSACTIONS 16
+-
+-#endif /* _sdiovar_h_ */
+diff --git a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
+deleted file mode 100644
+index 1827b0b..0000000
+--- a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
++++ /dev/null
+@@ -1,4428 +0,0 @@
+-/*
+- * Copyright (c) 2010 Broadcom Corporation
+- *
+- * 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/kernel.h>
+-#include <linux/if_arp.h>
+-
+-#include <bcmutils.h>
+-
+-#include <asm/uaccess.h>
+-
+-#include <dngl_stats.h>
+-#include <dhd.h>
+-#include <dhdioctl.h>
+-#include <wlioctl.h>
+-
+-#include <linux/kthread.h>
+-#include <linux/netdevice.h>
+-#include <linux/sched.h>
+-#include <linux/etherdevice.h>
+-#include <linux/wireless.h>
+-#include <linux/ieee80211.h>
+-#include <net/cfg80211.h>
+-
+-#include <net/rtnetlink.h>
+-#include <linux/mmc/sdio_func.h>
+-#include <linux/firmware.h>
+-#include <wl_cfg80211.h>
+-
+-void sdioh_sdio_set_host_pm_flags(int flag);
+-
+-static struct sdio_func *cfg80211_sdio_func;
+-static struct wl_dev *wl_cfg80211_dev;
+-static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255};
+-
+-u32 wl_dbg_level = WL_DBG_ERR;
+-
+-#define WL_4329_FW_FILE "brcm/bcm4329-fullmac-4.bin"
+-#define WL_4329_NVRAM_FILE "brcm/bcm4329-fullmac-4.txt"
+-
+-/*
+-** cfg80211_ops api/callback list
+-*/
+-static s32 wl_cfg80211_change_iface(struct wiphy *wiphy,
+- struct net_device *ndev,
+- enum nl80211_iftype type, u32 *flags,
+- struct vif_params *params);
+-static s32 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
+- struct cfg80211_scan_request *request,
+- struct cfg80211_ssid *this_ssid);
+-static s32 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
+- struct cfg80211_scan_request *request);
+-static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed);
+-static s32 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
+- struct cfg80211_ibss_params *params);
+-static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy,
+- struct net_device *dev);
+-static s32 wl_cfg80211_get_station(struct wiphy *wiphy,
+- struct net_device *dev, u8 *mac,
+- struct station_info *sinfo);
+-static s32 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
+- struct net_device *dev, bool enabled,
+- s32 timeout);
+-static s32 wl_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
+- struct net_device *dev,
+- const u8 *addr,
+- const struct cfg80211_bitrate_mask
+- *mask);
+-static int wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
+- struct cfg80211_connect_params *sme);
+-static s32 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
+- u16 reason_code);
+-static s32 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
+- enum nl80211_tx_power_setting type,
+- s32 dbm);
+-static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm);
+-static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
+- struct net_device *dev, u8 key_idx,
+- bool unicast, bool multicast);
+-static s32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
+- u8 key_idx, bool pairwise, const u8 *mac_addr,
+- struct key_params *params);
+-static s32 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
+- u8 key_idx, bool pairwise, const u8 *mac_addr);
+-static s32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
+- u8 key_idx, bool pairwise, const u8 *mac_addr,
+- void *cookie, void (*callback) (void *cookie,
+- struct
+- key_params *
+- params));
+-static s32 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
+- struct net_device *dev,
+- u8 key_idx);
+-static s32 wl_cfg80211_resume(struct wiphy *wiphy);
+-static s32 wl_cfg80211_suspend(struct wiphy *wiphy);
+-static s32 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
+- struct cfg80211_pmksa *pmksa);
+-static s32 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
+- struct cfg80211_pmksa *pmksa);
+-static s32 wl_cfg80211_flush_pmksa(struct wiphy *wiphy,
+- struct net_device *dev);
+-/*
+-** event & event Q handlers for cfg80211 interfaces
+-*/
+-static s32 wl_create_event_handler(struct wl_priv *wl);
+-static void wl_destroy_event_handler(struct wl_priv *wl);
+-static s32 wl_event_handler(void *data);
+-static void wl_init_eq(struct wl_priv *wl);
+-static void wl_flush_eq(struct wl_priv *wl);
+-static void wl_lock_eq(struct wl_priv *wl);
+-static void wl_unlock_eq(struct wl_priv *wl);
+-static void wl_init_eq_lock(struct wl_priv *wl);
+-static void wl_init_eloop_handler(struct wl_event_loop *el);
+-static struct wl_event_q *wl_deq_event(struct wl_priv *wl);
+-static s32 wl_enq_event(struct wl_priv *wl, u32 type,
+- const wl_event_msg_t *msg, void *data);
+-static void wl_put_event(struct wl_event_q *e);
+-static void wl_wakeup_event(struct wl_priv *wl);
+-static s32 wl_notify_connect_status(struct wl_priv *wl,
+- struct net_device *ndev,
+- const wl_event_msg_t *e, void *data);
+-static s32 wl_notify_roaming_status(struct wl_priv *wl,
+- struct net_device *ndev,
+- const wl_event_msg_t *e, void *data);
+-static s32 wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev,
+- const wl_event_msg_t *e, void *data);
+-static s32 wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
+- const wl_event_msg_t *e, void *data,
+- bool completed);
+-static s32 wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev,
+- const wl_event_msg_t *e, void *data);
+-static s32 wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev,
+- const wl_event_msg_t *e, void *data);
+-
+-/*
+-** register/deregister sdio function
+-*/
+-struct sdio_func *wl_cfg80211_get_sdio_func(void);
+-static void wl_clear_sdio_func(void);
+-
+-/*
+-** ioctl utilites
+-*/
+-static s32 wl_dev_bufvar_get(struct net_device *dev, s8 *name, s8 *buf,
+- s32 buf_len);
+-static __used s32 wl_dev_bufvar_set(struct net_device *dev, s8 *name,
+- s8 *buf, s32 len);
+-static s32 wl_dev_intvar_set(struct net_device *dev, s8 *name, s32 val);
+-static s32 wl_dev_intvar_get(struct net_device *dev, s8 *name,
+- s32 *retval);
+-static s32 wl_dev_ioctl(struct net_device *dev, u32 cmd, void *arg,
+- u32 len);
+-
+-/*
+-** cfg80211 set_wiphy_params utilities
+-*/
+-static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold);
+-static s32 wl_set_rts(struct net_device *dev, u32 frag_threshold);
+-static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l);
+-
+-/*
+-** wl profile utilities
+-*/
+-static s32 wl_update_prof(struct wl_priv *wl, const wl_event_msg_t *e,
+- void *data, s32 item);
+-static void *wl_read_prof(struct wl_priv *wl, s32 item);
+-static void wl_init_prof(struct wl_profile *prof);
+-
+-/*
+-** cfg80211 connect utilites
+-*/
+-static s32 wl_set_wpa_version(struct net_device *dev,
+- struct cfg80211_connect_params *sme);
+-static s32 wl_set_auth_type(struct net_device *dev,
+- struct cfg80211_connect_params *sme);
+-static s32 wl_set_set_cipher(struct net_device *dev,
+- struct cfg80211_connect_params *sme);
+-static s32 wl_set_key_mgmt(struct net_device *dev,
+- struct cfg80211_connect_params *sme);
+-static s32 wl_set_set_sharedkey(struct net_device *dev,
+- struct cfg80211_connect_params *sme);
+-static s32 wl_get_assoc_ies(struct wl_priv *wl);
+-static void wl_clear_assoc_ies(struct wl_priv *wl);
+-static void wl_ch_to_chanspec(int ch,
+- struct wl_join_params *join_params, size_t *join_params_size);
+-
+-/*
+-** information element utilities
+-*/
+-static __used s32 wl_add_ie(struct wl_priv *wl, u8 t, u8 l, u8 *v);
+-static s32 wl_mode_to_nl80211_iftype(s32 mode);
+-static struct wireless_dev *wl_alloc_wdev(s32 sizeof_iface,
+- struct device *dev);
+-static void wl_free_wdev(struct wl_priv *wl);
+-static s32 wl_inform_bss(struct wl_priv *wl);
+-static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi);
+-static s32 wl_update_bss_info(struct wl_priv *wl);
+-static s32 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
+- u8 key_idx, const u8 *mac_addr,
+- struct key_params *params);
+-
+-/*
+-** key indianess swap utilities
+-*/
+-static void swap_key_from_BE(struct wl_wsec_key *key);
+-static void swap_key_to_BE(struct wl_wsec_key *key);
+-
+-/*
+-** wl_priv memory init/deinit utilities
+-*/
+-static s32 wl_init_priv_mem(struct wl_priv *wl);
+-static void wl_deinit_priv_mem(struct wl_priv *wl);
+-
+-static void wl_delay(u32 ms);
+-
+-/*
+-** store/restore cfg80211 instance data
+-*/
+-static void wl_set_drvdata(struct wl_dev *dev, void *data);
+-static void *wl_get_drvdata(struct wl_dev *dev);
+-
+-/*
+-** ibss mode utilities
+-*/
+-static bool wl_is_ibssmode(struct wl_priv *wl);
+-
+-/*
+-** dongle up/down , default configuration utilities
+-*/
+-static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e);
+-static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e);
+-static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e);
+-static void wl_link_down(struct wl_priv *wl);
+-static s32 wl_dongle_mode(struct net_device *ndev, s32 iftype);
+-static s32 __wl_cfg80211_up(struct wl_priv *wl);
+-static s32 __wl_cfg80211_down(struct wl_priv *wl);
+-static s32 wl_dongle_probecap(struct wl_priv *wl);
+-static void wl_init_conf(struct wl_conf *conf);
+-
+-/*
+-** dongle configuration utilities
+-*/
+-#ifndef EMBEDDED_PLATFORM
+-static s32 wl_dongle_mode(struct net_device *ndev, s32 iftype);
+-static s32 wl_dongle_country(struct net_device *ndev, u8 ccode);
+-static s32 wl_dongle_up(struct net_device *ndev, u32 up);
+-static s32 wl_dongle_power(struct net_device *ndev, u32 power_mode);
+-static s32 wl_dongle_glom(struct net_device *ndev, u32 glom,
+- u32 dongle_align);
+-static s32 wl_dongle_offload(struct net_device *ndev, s32 arpoe,
+- s32 arp_ol);
+-static s32 wl_pattern_atoh(s8 *src, s8 *dst);
+-static s32 wl_dongle_filter(struct net_device *ndev, u32 filter_mode);
+-static s32 wl_update_wiphybands(struct wl_priv *wl);
+-#endif /* !EMBEDDED_PLATFORM */
+-
+-static s32 wl_dongle_eventmsg(struct net_device *ndev);
+-static s32 wl_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
+- s32 scan_unassoc_time, s32 scan_passive_time);
+-static s32 wl_config_dongle(struct wl_priv *wl, bool need_lock);
+-static s32 wl_dongle_roam(struct net_device *ndev, u32 roamvar,
+- u32 bcn_timeout);
+-
+-/*
+-** iscan handler
+-*/
+-static void wl_iscan_timer(unsigned long data);
+-static void wl_term_iscan(struct wl_priv *wl);
+-static s32 wl_init_iscan(struct wl_priv *wl);
+-static s32 wl_iscan_thread(void *data);
+-static s32 wl_dev_iovar_setbuf(struct net_device *dev, s8 *iovar,
+- void *param, s32 paramlen, void *bufptr,
+- s32 buflen);
+-static s32 wl_dev_iovar_getbuf(struct net_device *dev, s8 *iovar,
+- void *param, s32 paramlen, void *bufptr,
+- s32 buflen);
+-static s32 wl_run_iscan(struct wl_iscan_ctrl *iscan, struct wlc_ssid *ssid,
+- u16 action);
+-static s32 wl_do_iscan(struct wl_priv *wl);
+-static s32 wl_wakeup_iscan(struct wl_iscan_ctrl *iscan);
+-static s32 wl_invoke_iscan(struct wl_priv *wl);
+-static s32 wl_get_iscan_results(struct wl_iscan_ctrl *iscan, u32 *status,
+- struct wl_scan_results **bss_list);
+-static void wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted);
+-static void wl_init_iscan_eloop(struct wl_iscan_eloop *el);
+-static s32 wl_iscan_done(struct wl_priv *wl);
+-static s32 wl_iscan_pending(struct wl_priv *wl);
+-static s32 wl_iscan_inprogress(struct wl_priv *wl);
+-static s32 wl_iscan_aborted(struct wl_priv *wl);
+-
+-/*
+-** fw/nvram downloading handler
+-*/
+-static void wl_init_fw(struct wl_fw_ctrl *fw);
+-
+-/*
+-* find most significant bit set
+-*/
+-static __used u32 wl_find_msb(u16 bit16);
+-
+-/*
+-* update pmklist to dongle
+-*/
+-static __used s32 wl_update_pmklist(struct net_device *dev,
+- struct wl_pmk_list *pmk_list, s32 err);
+-
+-static void wl_set_mpc(struct net_device *ndev, int mpc);
+-
+-/*
+-* debufs support
+-*/
+-static int wl_debugfs_add_netdev_params(struct wl_priv *wl);
+-static void wl_debugfs_remove_netdev(struct wl_priv *wl);
+-
+-#define WL_PRIV_GET() \
+- ({ \
+- struct wl_iface *ci; \
+- if (unlikely(!(wl_cfg80211_dev && \
+- (ci = wl_get_drvdata(wl_cfg80211_dev))))) { \
+- WL_ERR("wl_cfg80211_dev is unavailable\n"); \
+- BUG(); \
+- } \
+- ci_to_wl(ci); \
+-})
+-
+-#define CHECK_SYS_UP() \
+-do { \
+- struct wl_priv *wl = wiphy_to_wl(wiphy); \
+- if (unlikely(!test_bit(WL_STATUS_READY, &wl->status))) { \
+- WL_INFO("device is not ready : status (%d)\n", \
+- (int)wl->status); \
+- return -EIO; \
+- } \
+-} while (0)
+-
+-extern int dhd_wait_pend8021x(struct net_device *dev);
+-#define CHAN2G(_channel, _freq, _flags) { \
+- .band = IEEE80211_BAND_2GHZ, \
+- .center_freq = (_freq), \
+- .hw_value = (_channel), \
+- .flags = (_flags), \
+- .max_antenna_gain = 0, \
+- .max_power = 30, \
+-}
+-
+-#define CHAN5G(_channel, _flags) { \
+- .band = IEEE80211_BAND_5GHZ, \
+- .center_freq = 5000 + (5 * (_channel)), \
+- .hw_value = (_channel), \
+- .flags = (_flags), \
+- .max_antenna_gain = 0, \
+- .max_power = 30, \
+-}
+-
+-#define RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2)
+-#define RATETAB_ENT(_rateid, _flags) \
+- { \
+- .bitrate = RATE_TO_BASE100KBPS(_rateid), \
+- .hw_value = (_rateid), \
+- .flags = (_flags), \
+- }
+-
+-static struct ieee80211_rate __wl_rates[] = {
+- RATETAB_ENT(WLC_RATE_1M, 0),
+- RATETAB_ENT(WLC_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE),
+- RATETAB_ENT(WLC_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE),
+- RATETAB_ENT(WLC_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE),
+- RATETAB_ENT(WLC_RATE_6M, 0),
+- RATETAB_ENT(WLC_RATE_9M, 0),
+- RATETAB_ENT(WLC_RATE_12M, 0),
+- RATETAB_ENT(WLC_RATE_18M, 0),
+- RATETAB_ENT(WLC_RATE_24M, 0),
+- RATETAB_ENT(WLC_RATE_36M, 0),
+- RATETAB_ENT(WLC_RATE_48M, 0),
+- RATETAB_ENT(WLC_RATE_54M, 0),
+-};
+-
+-#define wl_a_rates (__wl_rates + 4)
+-#define wl_a_rates_size 8
+-#define wl_g_rates (__wl_rates + 0)
+-#define wl_g_rates_size 12
+-
+-static struct ieee80211_channel __wl_2ghz_channels[] = {
+- CHAN2G(1, 2412, 0),
+- CHAN2G(2, 2417, 0),
+- CHAN2G(3, 2422, 0),
+- CHAN2G(4, 2427, 0),
+- CHAN2G(5, 2432, 0),
+- CHAN2G(6, 2437, 0),
+- CHAN2G(7, 2442, 0),
+- CHAN2G(8, 2447, 0),
+- CHAN2G(9, 2452, 0),
+- CHAN2G(10, 2457, 0),
+- CHAN2G(11, 2462, 0),
+- CHAN2G(12, 2467, 0),
+- CHAN2G(13, 2472, 0),
+- CHAN2G(14, 2484, 0),
+-};
+-
+-static struct ieee80211_channel __wl_5ghz_a_channels[] = {
+- CHAN5G(34, 0), CHAN5G(36, 0),
+- CHAN5G(38, 0), CHAN5G(40, 0),
+- CHAN5G(42, 0), CHAN5G(44, 0),
+- CHAN5G(46, 0), CHAN5G(48, 0),
+- CHAN5G(52, 0), CHAN5G(56, 0),
+- CHAN5G(60, 0), CHAN5G(64, 0),
+- CHAN5G(100, 0), CHAN5G(104, 0),
+- CHAN5G(108, 0), CHAN5G(112, 0),
+- CHAN5G(116, 0), CHAN5G(120, 0),
+- CHAN5G(124, 0), CHAN5G(128, 0),
+- CHAN5G(132, 0), CHAN5G(136, 0),
+- CHAN5G(140, 0), CHAN5G(149, 0),
+- CHAN5G(153, 0), CHAN5G(157, 0),
+- CHAN5G(161, 0), CHAN5G(165, 0),
+- CHAN5G(184, 0), CHAN5G(188, 0),
+- CHAN5G(192, 0), CHAN5G(196, 0),
+- CHAN5G(200, 0), CHAN5G(204, 0),
+- CHAN5G(208, 0), CHAN5G(212, 0),
+- CHAN5G(216, 0),
+-};
+-
+-static struct ieee80211_channel __wl_5ghz_n_channels[] = {
+- CHAN5G(32, 0), CHAN5G(34, 0),
+- CHAN5G(36, 0), CHAN5G(38, 0),
+- CHAN5G(40, 0), CHAN5G(42, 0),
+- CHAN5G(44, 0), CHAN5G(46, 0),
+- CHAN5G(48, 0), CHAN5G(50, 0),
+- CHAN5G(52, 0), CHAN5G(54, 0),
+- CHAN5G(56, 0), CHAN5G(58, 0),
+- CHAN5G(60, 0), CHAN5G(62, 0),
+- CHAN5G(64, 0), CHAN5G(66, 0),
+- CHAN5G(68, 0), CHAN5G(70, 0),
+- CHAN5G(72, 0), CHAN5G(74, 0),
+- CHAN5G(76, 0), CHAN5G(78, 0),
+- CHAN5G(80, 0), CHAN5G(82, 0),
+- CHAN5G(84, 0), CHAN5G(86, 0),
+- CHAN5G(88, 0), CHAN5G(90, 0),
+- CHAN5G(92, 0), CHAN5G(94, 0),
+- CHAN5G(96, 0), CHAN5G(98, 0),
+- CHAN5G(100, 0), CHAN5G(102, 0),
+- CHAN5G(104, 0), CHAN5G(106, 0),
+- CHAN5G(108, 0), CHAN5G(110, 0),
+- CHAN5G(112, 0), CHAN5G(114, 0),
+- CHAN5G(116, 0), CHAN5G(118, 0),
+- CHAN5G(120, 0), CHAN5G(122, 0),
+- CHAN5G(124, 0), CHAN5G(126, 0),
+- CHAN5G(128, 0), CHAN5G(130, 0),
+- CHAN5G(132, 0), CHAN5G(134, 0),
+- CHAN5G(136, 0), CHAN5G(138, 0),
+- CHAN5G(140, 0), CHAN5G(142, 0),
+- CHAN5G(144, 0), CHAN5G(145, 0),
+- CHAN5G(146, 0), CHAN5G(147, 0),
+- CHAN5G(148, 0), CHAN5G(149, 0),
+- CHAN5G(150, 0), CHAN5G(151, 0),
+- CHAN5G(152, 0), CHAN5G(153, 0),
+- CHAN5G(154, 0), CHAN5G(155, 0),
+- CHAN5G(156, 0), CHAN5G(157, 0),
+- CHAN5G(158, 0), CHAN5G(159, 0),
+- CHAN5G(160, 0), CHAN5G(161, 0),
+- CHAN5G(162, 0), CHAN5G(163, 0),
+- CHAN5G(164, 0), CHAN5G(165, 0),
+- CHAN5G(166, 0), CHAN5G(168, 0),
+- CHAN5G(170, 0), CHAN5G(172, 0),
+- CHAN5G(174, 0), CHAN5G(176, 0),
+- CHAN5G(178, 0), CHAN5G(180, 0),
+- CHAN5G(182, 0), CHAN5G(184, 0),
+- CHAN5G(186, 0), CHAN5G(188, 0),
+- CHAN5G(190, 0), CHAN5G(192, 0),
+- CHAN5G(194, 0), CHAN5G(196, 0),
+- CHAN5G(198, 0), CHAN5G(200, 0),
+- CHAN5G(202, 0), CHAN5G(204, 0),
+- CHAN5G(206, 0), CHAN5G(208, 0),
+- CHAN5G(210, 0), CHAN5G(212, 0),
+- CHAN5G(214, 0), CHAN5G(216, 0),
+- CHAN5G(218, 0), CHAN5G(220, 0),
+- CHAN5G(222, 0), CHAN5G(224, 0),
+- CHAN5G(226, 0), CHAN5G(228, 0),
+-};
+-
+-static struct ieee80211_supported_band __wl_band_2ghz = {
+- .band = IEEE80211_BAND_2GHZ,
+- .channels = __wl_2ghz_channels,
+- .n_channels = ARRAY_SIZE(__wl_2ghz_channels),
+- .bitrates = wl_g_rates,
+- .n_bitrates = wl_g_rates_size,
+-};
+-
+-static struct ieee80211_supported_band __wl_band_5ghz_a = {
+- .band = IEEE80211_BAND_5GHZ,
+- .channels = __wl_5ghz_a_channels,
+- .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
+- .bitrates = wl_a_rates,
+- .n_bitrates = wl_a_rates_size,
+-};
+-
+-static struct ieee80211_supported_band __wl_band_5ghz_n = {
+- .band = IEEE80211_BAND_5GHZ,
+- .channels = __wl_5ghz_n_channels,
+- .n_channels = ARRAY_SIZE(__wl_5ghz_n_channels),
+- .bitrates = wl_a_rates,
+- .n_bitrates = wl_a_rates_size,
+-};
+-
+-static const u32 __wl_cipher_suites[] = {
+- WLAN_CIPHER_SUITE_WEP40,
+- WLAN_CIPHER_SUITE_WEP104,
+- WLAN_CIPHER_SUITE_TKIP,
+- WLAN_CIPHER_SUITE_CCMP,
+- WLAN_CIPHER_SUITE_AES_CMAC,
+-};
+-
+-static void swap_key_from_BE(struct wl_wsec_key *key)
+-{
+- key->index = cpu_to_le32(key->index);
+- key->len = cpu_to_le32(key->len);
+- key->algo = cpu_to_le32(key->algo);
+- key->flags = cpu_to_le32(key->flags);
+- key->rxiv.hi = cpu_to_le32(key->rxiv.hi);
+- key->rxiv.lo = cpu_to_le16(key->rxiv.lo);
+- key->iv_initialized = cpu_to_le32(key->iv_initialized);
+-}
+-
+-static void swap_key_to_BE(struct wl_wsec_key *key)
+-{
+- key->index = le32_to_cpu(key->index);
+- key->len = le32_to_cpu(key->len);
+- key->algo = le32_to_cpu(key->algo);
+- key->flags = le32_to_cpu(key->flags);
+- key->rxiv.hi = le32_to_cpu(key->rxiv.hi);
+- key->rxiv.lo = le16_to_cpu(key->rxiv.lo);
+- key->iv_initialized = le32_to_cpu(key->iv_initialized);
+-}
+-
+-static s32
+-wl_dev_ioctl(struct net_device *dev, u32 cmd, void *arg, u32 len)
+-{
+- struct ifreq ifr;
+- struct wl_ioctl ioc;
+- mm_segment_t fs;
+- s32 err = 0;
+-
+- memset(&ioc, 0, sizeof(ioc));
+- ioc.cmd = cmd;
+- ioc.buf = arg;
+- ioc.len = len;
+- strcpy(ifr.ifr_name, dev->name);
+- ifr.ifr_data = (caddr_t)&ioc;
+-
+- fs = get_fs();
+- set_fs(get_ds());
+- err = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
+- set_fs(fs);
+-
+- return err;
+-}
+-
+-static s32
+-wl_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
+- enum nl80211_iftype type, u32 *flags,
+- struct vif_params *params)
+-{
+- struct wl_priv *wl = wiphy_to_wl(wiphy);
+- struct wireless_dev *wdev;
+- s32 infra = 0;
+- s32 err = 0;
+-
+- WL_TRACE("Enter\n");
+- CHECK_SYS_UP();
+-
+- switch (type) {
+- case NL80211_IFTYPE_MONITOR:
+- case NL80211_IFTYPE_WDS:
+- WL_ERR("type (%d) : currently we do not support this type\n",
+- type);
+- return -EOPNOTSUPP;
+- case NL80211_IFTYPE_ADHOC:
+- wl->conf->mode = WL_MODE_IBSS;
+- infra = 0;
+- break;
+- case NL80211_IFTYPE_STATION:
+- wl->conf->mode = WL_MODE_BSS;
+- infra = 1;
+- break;
+- default:
+- err = -EINVAL;
+- goto done;
+- }
+-
+- infra = cpu_to_le32(infra);
+- err = wl_dev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra));
+- if (unlikely(err)) {
+- WL_ERR("WLC_SET_INFRA error (%d)\n", err);
+- err = -EAGAIN;
+- } else {
+- wdev = ndev->ieee80211_ptr;
+- wdev->iftype = type;
+- }
+-
+- WL_INFO("IF Type = %s\n",
+- (wl->conf->mode == WL_MODE_IBSS) ? "Adhoc" : "Infra");
+-
+-done:
+- WL_TRACE("Exit\n");
+-
+- return err;
+-}
+-
+-static void wl_iscan_prep(struct wl_scan_params *params, struct wlc_ssid *ssid)
+-{
+- memcpy(params->bssid, ether_bcast, ETH_ALEN);
+- params->bss_type = DOT11_BSSTYPE_ANY;
+- params->scan_type = 0;
+- params->nprobes = -1;
+- params->active_time = -1;
+- params->passive_time = -1;
+- params->home_time = -1;
+- params->channel_num = 0;
+-
+- params->nprobes = cpu_to_le32(params->nprobes);
+- params->active_time = cpu_to_le32(params->active_time);
+- params->passive_time = cpu_to_le32(params->passive_time);
+- params->home_time = cpu_to_le32(params->home_time);
+- if (ssid && ssid->SSID_len)
+- memcpy(¶ms->ssid, ssid, sizeof(wlc_ssid_t));
+-
+-}
+-
+-static s32
+-wl_dev_iovar_setbuf(struct net_device *dev, s8 * iovar, void *param,
+- s32 paramlen, void *bufptr, s32 buflen)
+-{
+- s32 iolen;
+-
+- iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
+- BUG_ON(!iolen);
+-
+- return wl_dev_ioctl(dev, WLC_SET_VAR, bufptr, iolen);
+-}
+-
+-static s32
+-wl_dev_iovar_getbuf(struct net_device *dev, s8 * iovar, void *param,
+- s32 paramlen, void *bufptr, s32 buflen)
+-{
+- s32 iolen;
+-
+- iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
+- BUG_ON(!iolen);
+-
+- return wl_dev_ioctl(dev, WLC_GET_VAR, bufptr, buflen);
+-}
+-
+-static s32
+-wl_run_iscan(struct wl_iscan_ctrl *iscan, struct wlc_ssid *ssid, u16 action)
+-{
+- s32 params_size =
+- (WL_SCAN_PARAMS_FIXED_SIZE + offsetof(wl_iscan_params_t, params));
+- struct wl_iscan_params *params;
+- s32 err = 0;
+-
+- if (ssid && ssid->SSID_len)
+- params_size += sizeof(struct wlc_ssid);
+- params = kzalloc(params_size, GFP_KERNEL);
+- if (unlikely(!params))
+- return -ENOMEM;
+- BUG_ON(params_size >= WLC_IOCTL_SMLEN);
+-
+- wl_iscan_prep(¶ms->params, ssid);
+-
+- params->version = cpu_to_le32(ISCAN_REQ_VERSION);
+- params->action = cpu_to_le16(action);
+- params->scan_duration = cpu_to_le16(0);
+-
+- /* params_size += offsetof(wl_iscan_params_t, params); */
+- err = wl_dev_iovar_setbuf(iscan->dev, "iscan", params, params_size,
+- iscan->ioctl_buf, WLC_IOCTL_SMLEN);
+- if (unlikely(err)) {
+- if (err == -EBUSY) {
+- WL_INFO("system busy : iscan canceled\n");
+- } else {
+- WL_ERR("error (%d)\n", err);
+- }
+- }
+- kfree(params);
+- return err;
+-}
+-
+-static s32 wl_do_iscan(struct wl_priv *wl)
+-{
+- struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
+- struct net_device *ndev = wl_to_ndev(wl);
+- struct wlc_ssid ssid;
+- s32 passive_scan;
+- s32 err = 0;
+-
+- /* Broadcast scan by default */
+- memset(&ssid, 0, sizeof(ssid));
+-
+- iscan->state = WL_ISCAN_STATE_SCANING;
+-
+- passive_scan = wl->active_scan ? 0 : 1;
+- err = wl_dev_ioctl(wl_to_ndev(wl), WLC_SET_PASSIVE_SCAN,
+- &passive_scan, sizeof(passive_scan));
+- if (unlikely(err)) {
+- WL_ERR("error (%d)\n", err);
+- return err;
+- }
+- wl_set_mpc(ndev, 0);
+- wl->iscan_kickstart = true;
+- wl_run_iscan(iscan, &ssid, WL_SCAN_ACTION_START);
+- mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
+- iscan->timer_on = 1;
+-
+- return err;
+-}
+-
+-static s32
+-__wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
+- struct cfg80211_scan_request *request,
+- struct cfg80211_ssid *this_ssid)
+-{
+- struct wl_priv *wl = ndev_to_wl(ndev);
+- struct cfg80211_ssid *ssids;
+- struct wl_scan_req *sr = wl_to_sr(wl);
+- s32 passive_scan;
+- bool iscan_req;
+- bool spec_scan;
+- s32 err = 0;
+-
+- if (unlikely(test_bit(WL_STATUS_SCANNING, &wl->status))) {
+- WL_ERR("Scanning already : status (%d)\n", (int)wl->status);
+- return -EAGAIN;
+- }
+- if (unlikely(test_bit(WL_STATUS_SCAN_ABORTING, &wl->status))) {
+- WL_ERR("Scanning being aborted : status (%d)\n",
+- (int)wl->status);
+- return -EAGAIN;
+- }
+- if (test_bit(WL_STATUS_CONNECTING, &wl->status)) {
+- WL_ERR("Connecting : status (%d)\n",
+- (int)wl->status);
+- return -EAGAIN;
+- }
+-
+- iscan_req = false;
+- spec_scan = false;
+- if (request) {
+- /* scan bss */
+- ssids = request->ssids;
+- if (wl->iscan_on && (!ssids || !ssids->ssid_len))
+- iscan_req = true;
+- } else {
+- /* scan in ibss */
+- /* we don't do iscan in ibss */
+- ssids = this_ssid;
+- }
+-
+- wl->scan_request = request;
+- set_bit(WL_STATUS_SCANNING, &wl->status);
+- if (iscan_req) {
+- err = wl_do_iscan(wl);
+- if (likely(!err))
+- return err;
+- else
+- goto scan_out;
+- } else {
+- WL_SCAN("ssid \"%s\", ssid_len (%d)\n",
+- ssids->ssid, ssids->ssid_len);
+- memset(&sr->ssid, 0, sizeof(sr->ssid));
+- sr->ssid.SSID_len =
+- min_t(u8, sizeof(sr->ssid.SSID), ssids->ssid_len);
+- if (sr->ssid.SSID_len) {
+- memcpy(sr->ssid.SSID, ssids->ssid, sr->ssid.SSID_len);
+- sr->ssid.SSID_len = cpu_to_le32(sr->ssid.SSID_len);
+- spec_scan = true;
+- } else {
+- WL_SCAN("Broadcast scan\n");
+- }
+-
+- passive_scan = wl->active_scan ? 0 : 1;
+- err = wl_dev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
+- &passive_scan, sizeof(passive_scan));
+- if (unlikely(err)) {
+- WL_ERR("WLC_SET_PASSIVE_SCAN error (%d)\n", err);
+- goto scan_out;
+- }
+- wl_set_mpc(ndev, 0);
+- err = wl_dev_ioctl(ndev, WLC_SCAN, &sr->ssid,
+- sizeof(sr->ssid));
+- if (err) {
+- if (err == -EBUSY) {
+- WL_INFO("system busy : scan for \"%s\" canceled\n",
+- sr->ssid.SSID);
+- } else {
+- WL_ERR("WLC_SCAN error (%d)\n", err);
+- }
+- wl_set_mpc(ndev, 1);
+- goto scan_out;
+- }
+- }
+-
+- return 0;
+-
+-scan_out:
+- clear_bit(WL_STATUS_SCANNING, &wl->status);
+- wl->scan_request = NULL;
+- return err;
+-}
+-
+-static s32
+-wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
+- struct cfg80211_scan_request *request)
+-{
+- s32 err = 0;
+-
+- WL_TRACE("Enter\n");
+-
+- CHECK_SYS_UP();
+-
+- err = __wl_cfg80211_scan(wiphy, ndev, request, NULL);
+- if (unlikely(err))
+- WL_ERR("scan error (%d)\n", err);
+-
+- WL_TRACE("Exit\n");
+- return err;
+-}
+-
+-static s32 wl_dev_intvar_set(struct net_device *dev, s8 *name, s32 val)
+-{
+- s8 buf[WLC_IOCTL_SMLEN];
+- u32 len;
+- s32 err = 0;
+-
+- val = cpu_to_le32(val);
+- len = bcm_mkiovar(name, (char *)(&val), sizeof(val), buf, sizeof(buf));
+- BUG_ON(!len);
+-
+- err = wl_dev_ioctl(dev, WLC_SET_VAR, buf, len);
+- if (unlikely(err))
+- WL_ERR("error (%d)\n", err);
+-
+- return err;
+-}
+-
+-static s32
+-wl_dev_intvar_get(struct net_device *dev, s8 *name, s32 *retval)
+-{
+- union {
+- s8 buf[WLC_IOCTL_SMLEN];
+- s32 val;
+- } var;
+- u32 len;
+- u32 data_null;
+- s32 err = 0;
+-
+- len =
+- bcm_mkiovar(name, (char *)(&data_null), 0, (char *)(&var),
+- sizeof(var.buf));
+- BUG_ON(!len);
+- err = wl_dev_ioctl(dev, WLC_GET_VAR, &var, len);
+- if (unlikely(err))
+- WL_ERR("error (%d)\n", err);
+-
+- *retval = le32_to_cpu(var.val);
+-
+- return err;
+-}
+-
+-static s32 wl_set_rts(struct net_device *dev, u32 rts_threshold)
+-{
+- s32 err = 0;
+-
+- err = wl_dev_intvar_set(dev, "rtsthresh", rts_threshold);
+- if (unlikely(err))
+- WL_ERR("Error (%d)\n", err);
+-
+- return err;
+-}
+-
+-static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold)
+-{
+- s32 err = 0;
+-
+- err = wl_dev_intvar_set(dev, "fragthresh", frag_threshold);
+- if (unlikely(err))
+- WL_ERR("Error (%d)\n", err);
+-
+- return err;
+-}
+-
+-static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l)
+-{
+- s32 err = 0;
+- u32 cmd = (l ? WLC_SET_LRL : WLC_SET_SRL);
+-
+- retry = cpu_to_le32(retry);
+- err = wl_dev_ioctl(dev, cmd, &retry, sizeof(retry));
+- if (unlikely(err)) {
+- WL_ERR("cmd (%d) , error (%d)\n", cmd, err);
+- return err;
+- }
+- return err;
+-}
+-
+-static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
+-{
+- struct wl_priv *wl = wiphy_to_wl(wiphy);
+- struct net_device *ndev = wl_to_ndev(wl);
+- s32 err = 0;
+-
+- WL_TRACE("Enter\n");
+- CHECK_SYS_UP();
+-
+- if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
+- (wl->conf->rts_threshold != wiphy->rts_threshold)) {
+- wl->conf->rts_threshold = wiphy->rts_threshold;
+- err = wl_set_rts(ndev, wl->conf->rts_threshold);
+- if (!err)
+- goto done;
+- }
+- if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
+- (wl->conf->frag_threshold != wiphy->frag_threshold)) {
+- wl->conf->frag_threshold = wiphy->frag_threshold;
+- err = wl_set_frag(ndev, wl->conf->frag_threshold);
+- if (!err)
+- goto done;
+- }
+- if (changed & WIPHY_PARAM_RETRY_LONG
+- && (wl->conf->retry_long != wiphy->retry_long)) {
+- wl->conf->retry_long = wiphy->retry_long;
+- err = wl_set_retry(ndev, wl->conf->retry_long, true);
+- if (!err)
+- goto done;
+- }
+- if (changed & WIPHY_PARAM_RETRY_SHORT
+- && (wl->conf->retry_short != wiphy->retry_short)) {
+- wl->conf->retry_short = wiphy->retry_short;
+- err = wl_set_retry(ndev, wl->conf->retry_short, false);
+- if (!err)
+- goto done;
+- }
+-
+-done:
+- WL_TRACE("Exit\n");
+- return err;
+-}
+-
+-static s32
+-wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
+- struct cfg80211_ibss_params *params)
+-{
+- struct wl_priv *wl = wiphy_to_wl(wiphy);
+- struct wl_join_params join_params;
+- size_t join_params_size = 0;
+- s32 err = 0;
+- s32 wsec = 0;
+- s32 bcnprd;
+-
+- WL_TRACE("Enter\n");
+- CHECK_SYS_UP();
+-
+- if (params->ssid)
+- WL_CONN("SSID: %s\n", params->ssid);
+- else {
+- WL_CONN("SSID: NULL, Not supported\n");
+- return -EOPNOTSUPP;
+- }
+-
+- if (params->bssid)
+- WL_CONN("BSSID: %02X %02X %02X %02X %02X %02X\n",
+- params->bssid[0], params->bssid[1], params->bssid[2],
+- params->bssid[3], params->bssid[4], params->bssid[5]);
+- else
+- WL_CONN("No BSSID specified\n");
+-
+- if (params->channel)
+- WL_CONN("channel: %d\n", params->channel->center_freq);
+- else
+- WL_CONN("no channel specified\n");
+-
+- if (params->channel_fixed)
+- WL_CONN("fixed channel required\n");
+- else
+- WL_CONN("no fixed channel required\n");
+-
+- if (params->ie && params->ie_len)
+- WL_CONN("ie len: %d\n", params->ie_len);
+- else
+- WL_CONN("no ie specified\n");
+-
+- if (params->beacon_interval)
+- WL_CONN("beacon interval: %d\n", params->beacon_interval);
+- else
+- WL_CONN("no beacon interval specified\n");
+-
+- if (params->basic_rates)
+- WL_CONN("basic rates: %08X\n", params->basic_rates);
+- else
+- WL_CONN("no basic rates specified\n");
+-
+- if (params->privacy)
+- WL_CONN("privacy required\n");
+- else
+- WL_CONN("no privacy required\n");
+-
+- /* Configure Privacy for starter */
+- if (params->privacy)
+- wsec |= WEP_ENABLED;
+-
+- err = wl_dev_intvar_set(dev, "wsec", wsec);
+- if (unlikely(err)) {
+- WL_ERR("wsec failed (%d)\n", err);
+- goto done;
+- }
+-
+- /* Configure Beacon Interval for starter */
+- if (params->beacon_interval)
+- bcnprd = cpu_to_le32(params->beacon_interval);
+- else
+- bcnprd = cpu_to_le32(100);
+-
+- err = wl_dev_ioctl(dev, WLC_SET_BCNPRD, &bcnprd, sizeof(bcnprd));
+- if (unlikely(err)) {
+- WL_ERR("WLC_SET_BCNPRD failed (%d)\n", err);
+- goto done;
+- }
+-
+- /* Configure required join parameter */
+- memset(&join_params, 0, sizeof(wl_join_params_t));
+-
+- /* SSID */
+- join_params.ssid.SSID_len =
+- (params->ssid_len > 32) ? 32 : params->ssid_len;
+- memcpy(join_params.ssid.SSID, params->ssid, join_params.ssid.SSID_len);
+- join_params.ssid.SSID_len = cpu_to_le32(join_params.ssid.SSID_len);
+- join_params_size = sizeof(join_params.ssid);
+- wl_update_prof(wl, NULL, &join_params.ssid, WL_PROF_SSID);
+-
+- /* BSSID */
+- if (params->bssid) {
+- memcpy(join_params.params.bssid, params->bssid, ETH_ALEN);
+- join_params_size =
+- sizeof(join_params.ssid) + WL_ASSOC_PARAMS_FIXED_SIZE;
+- } else {
+- memcpy(join_params.params.bssid, ether_bcast, ETH_ALEN);
+- }
+- wl_update_prof(wl, NULL, &join_params.params.bssid, WL_PROF_BSSID);
+-
+- /* Channel */
+- if (params->channel) {
+- u32 target_channel;
+-
+- wl->channel =
+- ieee80211_frequency_to_channel(
+- params->channel->center_freq);
+- if (params->channel_fixed) {
+- /* adding chanspec */
+- wl_ch_to_chanspec(wl->channel,
+- &join_params, &join_params_size);
+- }
+-
+- /* set channel for starter */
+- target_channel = cpu_to_le32(wl->channel);
+- err = wl_dev_ioctl(dev, WLC_SET_CHANNEL,
+- &target_channel, sizeof(target_channel));
+- if (unlikely(err)) {
+- WL_ERR("WLC_SET_CHANNEL failed (%d)\n", err);
+- goto done;
+- }
+- } else
+- wl->channel = 0;
+-
+- wl->ibss_starter = false;
+-
+-
+- err = wl_dev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size);
+- if (unlikely(err)) {
+- WL_ERR("WLC_SET_SSID failed (%d)\n", err);
+- goto done;
+- }
+-
+- set_bit(WL_STATUS_CONNECTING, &wl->status);
+-
+-done:
+- WL_TRACE("Exit\n");
+- return err;
+-}
+-
+-static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
+-{
+- struct wl_priv *wl = wiphy_to_wl(wiphy);
+- s32 err = 0;
+-
+- WL_TRACE("Enter\n");
+- CHECK_SYS_UP();
+-
+- wl_link_down(wl);
+-
+- WL_TRACE("Exit\n");
+-
+- return err;
+-}
+-
+-static s32
+-wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme)
+-{
+- struct wl_priv *wl = ndev_to_wl(dev);
+- struct wl_security *sec;
+- s32 val = 0;
+- s32 err = 0;
+-
+- if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
+- val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
+- else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
+- val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
+- else
+- val = WPA_AUTH_DISABLED;
+- WL_CONN("setting wpa_auth to 0x%0x\n", val);
+- err = wl_dev_intvar_set(dev, "wpa_auth", val);
+- if (unlikely(err)) {
+- WL_ERR("set wpa_auth failed (%d)\n", err);
+- return err;
+- }
+- sec = wl_read_prof(wl, WL_PROF_SEC);
+- sec->wpa_versions = sme->crypto.wpa_versions;
+- return err;
+-}
+-
+-static s32
+-wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
+-{
+- struct wl_priv *wl = ndev_to_wl(dev);
+- struct wl_security *sec;
+- s32 val = 0;
+- s32 err = 0;
+-
+- switch (sme->auth_type) {
+- case NL80211_AUTHTYPE_OPEN_SYSTEM:
+- val = 0;
+- WL_CONN("open system\n");
+- break;
+- case NL80211_AUTHTYPE_SHARED_KEY:
+- val = 1;
+- WL_CONN("shared key\n");
+- break;
+- case NL80211_AUTHTYPE_AUTOMATIC:
+- val = 2;
+- WL_CONN("automatic\n");
+- break;
+- case NL80211_AUTHTYPE_NETWORK_EAP:
+- WL_CONN("network eap\n");
+- default:
+- val = 2;
+- WL_ERR("invalid auth type (%d)\n", sme->auth_type);
+- break;
+- }
+-
+- err = wl_dev_intvar_set(dev, "auth", val);
+- if (unlikely(err)) {
+- WL_ERR("set auth failed (%d)\n", err);
+- return err;
+- }
+- sec = wl_read_prof(wl, WL_PROF_SEC);
+- sec->auth_type = sme->auth_type;
+- return err;
+-}
+-
+-static s32
+-wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
+-{
+- struct wl_priv *wl = ndev_to_wl(dev);
+- struct wl_security *sec;
+- s32 pval = 0;
+- s32 gval = 0;
+- s32 err = 0;
+-
+- if (sme->crypto.n_ciphers_pairwise) {
+- switch (sme->crypto.ciphers_pairwise[0]) {
+- case WLAN_CIPHER_SUITE_WEP40:
+- case WLAN_CIPHER_SUITE_WEP104:
+- pval = WEP_ENABLED;
+- break;
+- case WLAN_CIPHER_SUITE_TKIP:
+- pval = TKIP_ENABLED;
+- break;
+- case WLAN_CIPHER_SUITE_CCMP:
+- pval = AES_ENABLED;
+- break;
+- case WLAN_CIPHER_SUITE_AES_CMAC:
+- pval = AES_ENABLED;
+- break;
+- default:
+- WL_ERR("invalid cipher pairwise (%d)\n",
+- sme->crypto.ciphers_pairwise[0]);
+- return -EINVAL;
+- }
+- }
+- if (sme->crypto.cipher_group) {
+- switch (sme->crypto.cipher_group) {
+- case WLAN_CIPHER_SUITE_WEP40:
+- case WLAN_CIPHER_SUITE_WEP104:
+- gval = WEP_ENABLED;
+- break;
+- case WLAN_CIPHER_SUITE_TKIP:
+- gval = TKIP_ENABLED;
+- break;
+- case WLAN_CIPHER_SUITE_CCMP:
+- gval = AES_ENABLED;
+- break;
+- case WLAN_CIPHER_SUITE_AES_CMAC:
+- gval = AES_ENABLED;
+- break;
+- default:
+- WL_ERR("invalid cipher group (%d)\n",
+- sme->crypto.cipher_group);
+- return -EINVAL;
+- }
+- }
+-
+- WL_CONN("pval (%d) gval (%d)\n", pval, gval);
+- err = wl_dev_intvar_set(dev, "wsec", pval | gval);
+- if (unlikely(err)) {
+- WL_ERR("error (%d)\n", err);
+- return err;
+- }
+-
+- sec = wl_read_prof(wl, WL_PROF_SEC);
+- sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0];
+- sec->cipher_group = sme->crypto.cipher_group;
+-
+- return err;
+-}
+-
+-static s32
+-wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
+-{
+- struct wl_priv *wl = ndev_to_wl(dev);
+- struct wl_security *sec;
+- s32 val = 0;
+- s32 err = 0;
+-
+- if (sme->crypto.n_akm_suites) {
+- err = wl_dev_intvar_get(dev, "wpa_auth", &val);
+- if (unlikely(err)) {
+- WL_ERR("could not get wpa_auth (%d)\n", err);
+- return err;
+- }
+- if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) {
+- switch (sme->crypto.akm_suites[0]) {
+- case WLAN_AKM_SUITE_8021X:
+- val = WPA_AUTH_UNSPECIFIED;
+- break;
+- case WLAN_AKM_SUITE_PSK:
+- val = WPA_AUTH_PSK;
+- break;
+- default:
+- WL_ERR("invalid cipher group (%d)\n",
+- sme->crypto.cipher_group);
+- return -EINVAL;
+- }
+- } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
+- switch (sme->crypto.akm_suites[0]) {
+- case WLAN_AKM_SUITE_8021X:
+- val = WPA2_AUTH_UNSPECIFIED;
+- break;
+- case WLAN_AKM_SUITE_PSK:
+- val = WPA2_AUTH_PSK;
+- break;
+- default:
+- WL_ERR("invalid cipher group (%d)\n",
+- sme->crypto.cipher_group);
+- return -EINVAL;
+- }
+- }
+-
+- WL_CONN("setting wpa_auth to %d\n", val);
+- err = wl_dev_intvar_set(dev, "wpa_auth", val);
+- if (unlikely(err)) {
+- WL_ERR("could not set wpa_auth (%d)\n", err);
+- return err;
+- }
+- }
+- sec = wl_read_prof(wl, WL_PROF_SEC);
+- sec->wpa_auth = sme->crypto.akm_suites[0];
+-
+- return err;
+-}
+-
+-static s32
+-wl_set_set_sharedkey(struct net_device *dev,
+- struct cfg80211_connect_params *sme)
+-{
+- struct wl_priv *wl = ndev_to_wl(dev);
+- struct wl_security *sec;
+- struct wl_wsec_key key;
+- s32 val;
+- s32 err = 0;
+-
+- WL_CONN("key len (%d)\n", sme->key_len);
+- if (sme->key_len) {
+- sec = wl_read_prof(wl, WL_PROF_SEC);
+- WL_CONN("wpa_versions 0x%x cipher_pairwise 0x%x\n",
+- sec->wpa_versions, sec->cipher_pairwise);
+- if (!
+- (sec->wpa_versions & (NL80211_WPA_VERSION_1 |
+- NL80211_WPA_VERSION_2))
+-&& (sec->cipher_pairwise & (WLAN_CIPHER_SUITE_WEP40 |
+- WLAN_CIPHER_SUITE_WEP104))) {
+- memset(&key, 0, sizeof(key));
+- key.len = (u32) sme->key_len;
+- key.index = (u32) sme->key_idx;
+- if (unlikely(key.len > sizeof(key.data))) {
+- WL_ERR("Too long key length (%u)\n", key.len);
+- return -EINVAL;
+- }
+- memcpy(key.data, sme->key, key.len);
+- key.flags = WL_PRIMARY_KEY;
+- switch (sec->cipher_pairwise) {
+- case WLAN_CIPHER_SUITE_WEP40:
+- key.algo = CRYPTO_ALGO_WEP1;
+- break;
+- case WLAN_CIPHER_SUITE_WEP104:
+- key.algo = CRYPTO_ALGO_WEP128;
+- break;
+- default:
+- WL_ERR("Invalid algorithm (%d)\n",
+- sme->crypto.ciphers_pairwise[0]);
+- return -EINVAL;
+- }
+- /* Set the new key/index */
+- WL_CONN("key length (%d) key index (%d) algo (%d)\n",
+- key.len, key.index, key.algo);
+- WL_CONN("key \"%s\"\n", key.data);
+- swap_key_from_BE(&key);
+- err = wl_dev_ioctl(dev, WLC_SET_KEY, &key,
+- sizeof(key));
+- if (unlikely(err)) {
+- WL_ERR("WLC_SET_KEY error (%d)\n", err);
+- return err;
+- }
+- if (sec->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) {
+- WL_CONN("set auth_type to shared key\n");
+- val = 1; /* shared key */
+- err = wl_dev_intvar_set(dev, "auth", val);
+- if (unlikely(err)) {
+- WL_ERR("set auth failed (%d)\n", err);
+- return err;
+- }
+- }
+- }
+- }
+- return err;
+-}
+-
+-static s32
+-wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
+- struct cfg80211_connect_params *sme)
+-{
+- struct wl_priv *wl = wiphy_to_wl(wiphy);
+- struct ieee80211_channel *chan = sme->channel;
+- struct wl_join_params join_params;
+- size_t join_params_size;
+-
+- s32 err = 0;
+-
+- WL_TRACE("Enter\n");
+- CHECK_SYS_UP();
+-
+- if (unlikely(!sme->ssid)) {
+- WL_ERR("Invalid ssid\n");
+- return -EOPNOTSUPP;
+- }
+-
+- if (chan) {
+- wl->channel =
+- ieee80211_frequency_to_channel(chan->center_freq);
+- WL_CONN("channel (%d), center_req (%d)\n",
+- wl->channel, chan->center_freq);
+- } else
+- wl->channel = 0;
+-
+- WL_INFO("ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len);
+-
+- err = wl_set_wpa_version(dev, sme);
+- if (unlikely(err))
+- return err;
+-
+- err = wl_set_auth_type(dev, sme);
+- if (unlikely(err))
+- return err;
+-
+- err = wl_set_set_cipher(dev, sme);
+- if (unlikely(err))
+- return err;
+-
+- err = wl_set_key_mgmt(dev, sme);
+- if (unlikely(err))
+- return err;
+-
+- err = wl_set_set_sharedkey(dev, sme);
+- if (unlikely(err))
+- return err;
+-
+- wl_update_prof(wl, NULL, sme->bssid, WL_PROF_BSSID);
+- /*
+- ** Join with specific BSSID and cached SSID
+- ** If SSID is zero join based on BSSID only
+- */
+- memset(&join_params, 0, sizeof(join_params));
+- join_params_size = sizeof(join_params.ssid);
+-
+- join_params.ssid.SSID_len = min(sizeof(join_params.ssid.SSID), sme->ssid_len);
+-
Removes brcm80211 driver in drivers/staging. This is meant to be applied with a patch to add a backported driver from kernel v3.5 which is loaded into drivers/net/wireless. Signed-off-by: John Weber <rjohnweber@gmail.com> --- ...mx-3.0.35-remove-brcm80211-staging-driver.patch |123141 ++++++++++++++++++++ 1 files changed, 123142 insertions(+) create mode 100644 recipes-kernel/linux/linux-imx-3.0.35/wandboard-dual/0003-linux-imx-3.0.35-remove-brcm80211-staging-driver.patch