diff --git a/core/linux-sun7i/PKGBUILD b/core/linux-sun7i/PKGBUILD index b0ace674a..1c62407c1 100644 --- a/core/linux-sun7i/PKGBUILD +++ b/core/linux-sun7i/PKGBUILD @@ -4,35 +4,34 @@ buildarch=4 pkgbase=linux-sun7i -_commit=e906c090ca17ed30ed0e826df3c4d095e5f5c865 +_commit=8ea347bcb4b4a5e50ec0343afac579e933ce8402 _srcname=linux-sunxi-${_commit} _kernelname=${pkgbase#linux} _desc="sun7i" -pkgver=3.3.0 -pkgrel=10 +pkgver=3.4.79 +pkgrel=1 arch=('armv7h') -url="https://github.com/cubieboard2/linux-sunxi" +url="https://github.com/linux-sunxi/linux-sunxi/" license=('GPL2') makedepends=('xmlto' 'docbook-xsl' 'kmod' 'inetutils' 'bc' 'uboot-mkimage') options=('!strip') -source=("https://github.com/cubieboard2/linux-sunxi/archive/${_commit}.tar.gz" - "memset.patch" - 'config') -md5sums=('7fa48cc5b9d8917601aa1f95818a6a08' - '39be2896f0b968d61a19b33da75ce6e0' - '222d7ed0f04d1095cc4e650e9c28bdec') +source=("https://github.com/linux-sunxi/linux-sunxi/archive/${_commit}.tar.gz" + 'config' + 'working-bcmdhd-driver.patch') +md5sums=('a6f18158a7f8dcb552547ea958c24c6b' + '2f846d0509ed554324f966b2291cef10' + '07c260ca97572a830778362c7b744f9c') prepare() { cd "${srcdir}/${_srcname}" cat "${srcdir}/config" > ./.config - # memset fix for GCC 4.8 - patch -p1 -i ../memset.patch + # patch bcmdhd driver with a working version + patch -Np1 -i "${srcdir}/working-bcmdhd-driver.patch" # add pkgrel to extraversion sed -ri "s|^(EXTRAVERSION =)(.*)|\1 \2-${pkgrel}|" Makefile - sed -ri "138c MODULE_LICENSE(\"GPL\");" arch/arm/mach-sun7i/rf/bt_pm.c # don't run depmod on 'make install'. We'll do this ourselves in packaging sed -i '2iexit 0' scripts/depmod.sh diff --git a/core/linux-sun7i/config b/core/linux-sun7i/config index 4886862a5..e90326263 100644 --- a/core/linux-sun7i/config +++ b/core/linux-sun7i/config @@ -1,10 +1,9 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm 3.3.0-9 Kernel Configuration +# Linux/arm 3.4.79 Kernel Configuration # CONFIG_ARM=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y -CONFIG_HAVE_SCHED_CLOCK=y CONFIG_GENERIC_GPIO=y # CONFIG_ARCH_USES_GETTIMEOFFSET is not set CONFIG_GENERIC_CLOCKEVENTS=y @@ -26,6 +25,7 @@ CONFIG_ZONE_DMA=y CONFIG_NEED_DMA_MAP_STATE=y CONFIG_VECTORS_BASE=0xffff0000 CONFIG_ARM_PATCH_PHYS_VIRT=y +CONFIG_NEED_MACH_IO_H=y CONFIG_NEED_MACH_MEMORY_H=y CONFIG_GENERIC_BUG=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" @@ -41,9 +41,11 @@ CONFIG_LOCALVERSION="-ARCH" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_XZ=y CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_XZ is not set # CONFIG_KERNEL_LZO is not set CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y @@ -65,17 +67,15 @@ CONFIG_HAVE_GENERIC_HARDIRQS=y # IRQ subsystem # CONFIG_GENERIC_HARDIRQS=y -CONFIG_HAVE_SPARSE_IRQ=y CONFIG_GENERIC_IRQ_SHOW=y CONFIG_IRQ_DOMAIN=y -# CONFIG_SPARSE_IRQ is not set +# CONFIG_IRQ_DOMAIN_DEBUG is not set # # RCU Subsystem # CONFIG_TREE_PREEMPT_RCU=y CONFIG_PREEMPT_RCU=y -# CONFIG_RCU_TRACE is not set CONFIG_RCU_FANOUT=32 # CONFIG_RCU_FANOUT_EXACT is not set # CONFIG_RCU_FAST_NO_HZ is not set @@ -159,12 +159,16 @@ CONFIG_PROFILING=y CONFIG_OPROFILE=m CONFIG_HAVE_OPROFILE=y # CONFIG_KPROBES is not set +# CONFIG_JUMP_LABEL is not set CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_CONTIGUOUS=y CONFIG_USE_GENERIC_SMP_HELPERS=y CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_ARCH_JUMP_LABEL=y # # GCOV-based kernel profiling @@ -208,6 +212,7 @@ CONFIG_UNIXWARE_DISKLABEL=y # CONFIG_KARMA_PARTITION is not set CONFIG_EFI_PARTITION=y # CONFIG_SYSV68_PARTITION is not set +CONFIG_SUNXI_NAND_PARTITION=y # # IO Schedulers @@ -225,7 +230,7 @@ CONFIG_DEFAULT_IOSCHED="cfq" # CONFIG_INLINE_SPIN_LOCK_BH is not set # CONFIG_INLINE_SPIN_LOCK_IRQ is not set # CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set -# CONFIG_INLINE_SPIN_UNLOCK is not set +CONFIG_UNINLINE_SPIN_UNLOCK=y # CONFIG_INLINE_SPIN_UNLOCK_BH is not set # CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set # CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set @@ -256,8 +261,6 @@ CONFIG_FREEZER=y CONFIG_MMU=y # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_REALVIEW is not set -# CONFIG_ARCH_SUN6I is not set -CONFIG_ARCH_SUN7I=y # CONFIG_ARCH_VERSATILE is not set # CONFIG_ARCH_VEXPRESS is not set # CONFIG_ARCH_AT91 is not set @@ -290,13 +293,16 @@ CONFIG_ARCH_SUN7I=y # CONFIG_ARCH_W90X900 is not set # CONFIG_ARCH_TEGRA is not set # CONFIG_ARCH_PICOXCELL is not set +# CONFIG_ARCH_SUN4I is not set +# CONFIG_ARCH_SUN5I is not set +CONFIG_ARCH_SUN7I=y # CONFIG_ARCH_PNX4008 is not set # CONFIG_ARCH_PXA is not set # CONFIG_ARCH_MSM is not set # CONFIG_ARCH_SHMOBILE is not set # CONFIG_ARCH_RPC is not set # CONFIG_ARCH_SA1100 is not set -# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C24XX is not set # CONFIG_ARCH_S3C64XX is not set # CONFIG_ARCH_S5P64X0 is not set # CONFIG_ARCH_S5PC100 is not set @@ -319,10 +325,12 @@ CONFIG_ARCH_SUN7I=y # # -# Allwinner Platform Type +# Allwinner's sunxi options # -# CONFIG_AW_FPGA_PLATFORM is not set -CONFIG_AW_ASIC_PLATFORM=y +CONFIG_SW_DEBUG_UART=0 +CONFIG_SUNXI_MULTIPLATFORM=y +CONFIG_SUNXI_SCALING_MIN=720 +CONFIG_PLAT_SUNXI=y # # Processor Type @@ -371,6 +379,7 @@ CONFIG_MULTI_IRQ_HANDLER=y # CONFIG_ARM_ERRATA_754322 is not set # CONFIG_ARM_ERRATA_754327 is not set # CONFIG_ARM_ERRATA_764369 is not set +# CONFIG_ARM_ERRATA_775420 is not set CONFIG_ARM_GIC=y # CONFIG_FIQ_DEBUGGER is not set @@ -398,7 +407,6 @@ CONFIG_SCHED_SMT=y CONFIG_HAVE_ARM_SCU=y CONFIG_ARM_ARCH_TIMER=y CONFIG_HAVE_ARM_TWD=y -CONFIG_AW_TIME_DELAY=y CONFIG_VMSPLIT_3G=y # CONFIG_VMSPLIT_2G is not set # CONFIG_VMSPLIT_1G is not set @@ -470,7 +478,6 @@ CONFIG_CPU_FREQ_TABLE=y CONFIG_CPU_FREQ_STAT=y CONFIG_CPU_FREQ_STAT_DETAILS=y CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y -# CONFIG_CPU_FREQ_DEFAULT_GOV_BENCHMARK is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set @@ -478,18 +485,23 @@ CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y # CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_FANTASY is not set CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -CONFIG_CPU_FREQ_GOV_BENCHMARK=y CONFIG_CPU_FREQ_GOV_POWERSAVE=y CONFIG_CPU_FREQ_GOV_USERSPACE=y CONFIG_CPU_FREQ_GOV_ONDEMAND=y # CONFIG_CPU_FREQ_GOV_INTERACTIVE is not set CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -CONFIG_CPU_FREQ_GOV_FANTASYS=y +# CONFIG_CPU_FREQ_GOV_FANTASY is not set CONFIG_CPU_FREQ_USR_EVNT_NOTIFY=y CONFIG_CPU_FREQ_DVFS=y -# CONFIG_CPU_FREQ_DVFS_HW is not set -CONFIG_CPU_FREQ_EARLYSUSPEND=y + +# +# ARM CPU frequency scaling drivers +# +# CONFIG_ARM_EXYNOS4210_CPUFREQ is not set +# CONFIG_ARM_EXYNOS4X12_CPUFREQ is not set +# CONFIG_ARM_EXYNOS5250_CPUFREQ is not set # CONFIG_CPU_IDLE is not set +# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set # # Floating point emulation @@ -517,19 +529,12 @@ CONFIG_BINFMT_MISC=y # CONFIG_SUSPEND=y CONFIG_SUSPEND_FREEZER=y -CONFIG_PM_WATCHDOG_TIMEOUT=y CONFIG_HAS_WAKELOCK=y -CONFIG_HAS_EARLYSUSPEND=y CONFIG_WAKELOCK=y -CONFIG_WAKELOCK_STAT=y -CONFIG_USER_WAKELOCK=y -CONFIG_EARLYSUSPEND=y -CONFIG_EARLYSUSPEND_DELAY=y -# CONFIG_NO_USER_SPACE_SCREEN_ACCESS_CONTROL is not set -# CONFIG_CONSOLE_EARLYSUSPEND is not set -CONFIG_FB_EARLYSUSPEND=y CONFIG_PM_SLEEP=y CONFIG_PM_SLEEP_SMP=y +# CONFIG_PM_AUTOSLEEP is not set +# CONFIG_PM_WAKELOCKS is not set # CONFIG_PM_RUNTIME is not set CONFIG_PM=y # CONFIG_PM_DEBUG is not set @@ -638,6 +643,7 @@ CONFIG_NF_CONNTRACK_MARK=y CONFIG_NF_CONNTRACK_ZONES=y CONFIG_NF_CONNTRACK_PROCFS=y CONFIG_NF_CONNTRACK_EVENTS=y +# CONFIG_NF_CONNTRACK_TIMEOUT is not set CONFIG_NF_CONNTRACK_TIMESTAMP=y CONFIG_NF_CT_PROTO_DCCP=m CONFIG_NF_CT_PROTO_GRE=m @@ -655,6 +661,7 @@ CONFIG_NF_CONNTRACK_SANE=m CONFIG_NF_CONNTRACK_SIP=m CONFIG_NF_CONNTRACK_TFTP=m CONFIG_NF_CT_NETLINK=m +# CONFIG_NF_CT_NETLINK_TIMEOUT is not set CONFIG_NETFILTER_TPROXY=m CONFIG_NETFILTER_XTABLES=y @@ -676,6 +683,7 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m CONFIG_NETFILTER_XT_TARGET_HL=m CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m CONFIG_NETFILTER_XT_TARGET_LED=m +# CONFIG_NETFILTER_XT_TARGET_LOG is not set CONFIG_NETFILTER_XT_TARGET_MARK=m CONFIG_NETFILTER_XT_TARGET_NFLOG=m CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m @@ -761,7 +769,6 @@ CONFIG_IP_NF_MATCH_TTL=m CONFIG_IP_NF_FILTER=m CONFIG_IP_NF_TARGET_REJECT=m CONFIG_IP_NF_TARGET_REJECT_SKERR=y -CONFIG_IP_NF_TARGET_LOG=m CONFIG_IP_NF_TARGET_ULOG=m CONFIG_NF_NAT=m CONFIG_NF_NAT_NEEDED=y @@ -806,7 +813,6 @@ CONFIG_IP6_NF_MATCH_MH=m CONFIG_IP6_NF_MATCH_RPFILTER=m CONFIG_IP6_NF_MATCH_RT=m CONFIG_IP6_NF_TARGET_HL=m -CONFIG_IP6_NF_TARGET_LOG=m CONFIG_IP6_NF_FILTER=m CONFIG_IP6_NF_TARGET_REJECT=m CONFIG_IP6_NF_TARGET_REJECT_SKERR=y @@ -875,6 +881,8 @@ CONFIG_RFS_ACCEL=y CONFIG_XPS=y # CONFIG_NETPRIO_CGROUP is not set CONFIG_BQL=y +CONFIG_HAVE_BPF_JIT=y +# CONFIG_BPF_JIT is not set # # Network testing @@ -993,12 +1001,13 @@ CONFIG_MAC80211_LEDS=y # CONFIG_MAC80211_DEBUGFS is not set # CONFIG_MAC80211_DEBUG_MENU is not set # CONFIG_WIMAX is not set -CONFIG_RFKILL=m +CONFIG_RFKILL=y CONFIG_RFKILL_PM=y CONFIG_RFKILL_LEDS=y CONFIG_RFKILL_INPUT=y CONFIG_RFKILL_REGULATOR=m CONFIG_RFKILL_GPIO=m +CONFIG_SUNXI_RFKILL=y # CONFIG_NET_9P is not set # CONFIG_CAIF is not set # CONFIG_CEPH_LIB is not set @@ -1029,6 +1038,7 @@ CONFIG_REGMAP_SPI=y # CONFIG_DMA_SHARED_BUFFER is not set CONFIG_SYNC=y # CONFIG_SW_SYNC is not set +# CONFIG_CMA is not set # CONFIG_CONNECTOR is not set CONFIG_MTD=y # CONFIG_MTD_TESTS is not set @@ -1123,13 +1133,19 @@ CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 # CONFIG_ATA_OVER_ETH is not set # CONFIG_MG_DISK is not set # CONFIG_BLK_DEV_RBD is not set +CONFIG_SUNXI_NAND=y +CONFIG_SUNXI_NAND_COMPAT_DEV=y +# CONFIG_SUNXI_NAND_TEST is not set # # Misc devices # # CONFIG_SENSORS_LIS3LV02D is not set # CONFIG_AD525X_DPOT is not set +# CONFIG_SUN4I_VIBRATOR is not set +CONFIG_SUNXI_DBGREG=m # CONFIG_ATMEL_PWM is not set +CONFIG_SUNXI_PWM=m # CONFIG_ICS932S401 is not set # CONFIG_ENCLOSURE_SERVICES is not set # CONFIG_APDS9802ALS is not set @@ -1281,6 +1297,7 @@ CONFIG_DM_MULTIPATH_ST=m CONFIG_DM_DELAY=m # CONFIG_DM_UEVENT is not set CONFIG_DM_FLAKEY=m +# CONFIG_DM_VERITY is not set CONFIG_TARGET_CORE=m CONFIG_TCM_IBLOCK=m CONFIG_TCM_FILEIO=m @@ -1317,6 +1334,8 @@ CONFIG_ETHERNET=y # CONFIG_NET_VENDOR_BROADCOM is not set # CONFIG_NET_CALXEDA_XGMAC is not set # CONFIG_NET_VENDOR_CHELSIO is not set +CONFIG_NET_VENDOR_CIRRUS=y +# CONFIG_CS89x0 is not set # CONFIG_DM9000 is not set # CONFIG_DNET is not set # CONFIG_NET_VENDOR_FARADAY is not set @@ -1330,14 +1349,18 @@ CONFIG_NET_VENDOR_MICROCHIP=y # CONFIG_NET_VENDOR_SEEQ is not set # CONFIG_NET_VENDOR_SMSC is not set # CONFIG_NET_VENDOR_STMICRO is not set -# CONFIG_NET_VENDOR_SUNXI is not set -CONFIG_NET_VENDOR_SUN7I=y -CONFIG_SUN7I_EMAC=y +CONFIG_SUNXI_EMAC=y +CONFIG_SUNXI_GMAC=m +CONFIG_GMAC_SCRIPT_SYS=y +CONFIG_GMAC_CLK_SYS=y +CONFIG_GMAC_RING=y +# CONFIG_GMAC_CHAINED is not set CONFIG_PHYLIB=y # # MII PHY device drivers # +# CONFIG_AMD_PHY is not set # CONFIG_MARVELL_PHY is not set # CONFIG_DAVICOM_PHY is not set # CONFIG_QSEMI_PHY is not set @@ -1405,6 +1428,7 @@ CONFIG_USB_KC2190=y CONFIG_USB_NET_ZAURUS=m CONFIG_USB_NET_CX82310_ETH=m CONFIG_USB_NET_KALMIA=m +# CONFIG_USB_NET_QMI_WWAN is not set CONFIG_USB_HSO=m CONFIG_USB_NET_INT51X1=m CONFIG_USB_IPHETH=m @@ -1425,26 +1449,28 @@ CONFIG_ATH_COMMON=m # CONFIG_ATH_DEBUG is not set CONFIG_ATH9K_HW=m CONFIG_ATH9K_COMMON=m +CONFIG_ATH9K_BTCOEX_SUPPORT=y CONFIG_ATH9K=m # CONFIG_ATH9K_AHB is not set # CONFIG_ATH9K_DEBUGFS is not set # CONFIG_ATH9K_DFS_CERTIFIED is not set -CONFIG_ATH9K_RATE_CONTROL=y -CONFIG_ATH9K_BTCOEX_SUPPORT=y +# CONFIG_ATH9K_LEGACY_RATE_CONTROL is not set CONFIG_ATH9K_HTC=m # CONFIG_ATH9K_HTC_DEBUGFS is not set # CONFIG_CARL9170 is not set CONFIG_ATH6KL=m +# CONFIG_ATH6KL_SDIO is not set +# CONFIG_ATH6KL_USB is not set # CONFIG_ATH6KL_DEBUG is not set # CONFIG_B43 is not set -CONFIG_BCM4330=m # CONFIG_B43LEGACY is not set CONFIG_BCMDHD=m -CONFIG_BCMDHD_FW_PATH="/system/vendor/modules/fw_bcmxxxx.bin" -CONFIG_BCMDHD_NVRAM_PATH="/system/vendor/modules/nvram_apxxxx.txt" +CONFIG_BCMDHD_FW_PATH="/lib/firmware/ap6210/fw_bcmxxxx.bin" +CONFIG_BCMDHD_NVRAM_PATH="/lib/firmware/ap6210/nvram_apxxxx.txt" CONFIG_BCMDHD_OOB=y # CONFIG_BCMDHD_SDIO_IRQ is not set # CONFIG_BRCMFMAC is not set +CONFIG_BCM4330=m CONFIG_HOSTAP=m CONFIG_HOSTAP_FIRMWARE=y CONFIG_HOSTAP_FIRMWARE_NVRAM=y @@ -1476,6 +1502,7 @@ CONFIG_RT2X00_LIB_LEDS=y # CONFIG_RT2X00_DEBUG is not set CONFIG_RTL8192CU=m CONFIG_RTLWIFI=m +CONFIG_RTLWIFI_DEBUG=y CONFIG_RTL8192C_COMMON=m # CONFIG_WL1251 is not set # CONFIG_WL12XX_MENU is not set @@ -1487,13 +1514,13 @@ CONFIG_RTL8192CU_SW=m CONFIG_RTL8188EU=m # CONFIG_RTL8189ES is not set # CONFIG_RTL8723AS is not set +# CONFIG_RTXX7X_SW is not set # # Enable WiMAX (Networking options) to see the WiMAX drivers # # CONFIG_WAN is not set # CONFIG_ISDN is not set -# CONFIG_PHONE is not set # # Input device support @@ -1514,8 +1541,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 CONFIG_INPUT_EVDEV=y # CONFIG_INPUT_EVBUG is not set # CONFIG_INPUT_KEYRESET is not set -CONFIG_INPUT_INIT_CTP=y -CONFIG_INPUT_DEVICE=m # # Input Device Drivers @@ -1540,11 +1565,13 @@ CONFIG_INPUT_KEYBOARD=y # CONFIG_KEYBOARD_SAMSUNG is not set # CONFIG_KEYBOARD_STOWAWAY is not set # CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_OMAP4 is not set # CONFIG_KEYBOARD_XTKBD is not set -# CONFIG_SUN7I_KEYPAD is not set -# CONFIG_KEYBOARD_SW_KEYBOARD is not set -# CONFIG_IR_SUN6I is not set -CONFIG_IR_SUN7I=y +CONFIG_KEYBOARD_SUN4IKEYPAD=m +CONFIG_KEYBOARD_SUN4I_KEYBOARD=m +# CONFIG_KEYBOARD_SUN4I_KEYBOARD_FEX is not set +CONFIG_KEYBOARD_HV2605_KEYBOARD=m +CONFIG_IR_SUNXI=y CONFIG_INPUT_MOUSE=y CONFIG_MOUSE_PS2=y CONFIG_MOUSE_PS2_ALPS=y @@ -1560,12 +1587,11 @@ CONFIG_MOUSE_SERIAL=y # CONFIG_MOUSE_VSXXXAA is not set # CONFIG_MOUSE_GPIO is not set # CONFIG_MOUSE_SYNAPTICS_I2C is not set +# CONFIG_MOUSE_SYNAPTICS_USB is not set # CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_TABLET is not set # CONFIG_INPUT_TOUCHSCREEN is not set # CONFIG_INPUT_MISC is not set -# CONFIG_INPUT_GYR is not set -# CONFIG_INPUT_E_COMPASS is not set # # Hardware I/O ports @@ -1578,6 +1604,7 @@ CONFIG_SERIO_LIBPS2=y # CONFIG_SERIO_ALTERA_PS2 is not set # CONFIG_SERIO_PS2MULT is not set # CONFIG_GAMEPORT is not set +# CONFIG_GSENSOR is not set # # Character devices @@ -1603,6 +1630,7 @@ CONFIG_DEVKMEM=y # CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_SUNXI=y CONFIG_SERIAL_8250_NR_UARTS=1 CONFIG_SERIAL_8250_RUNTIME_UARTS=1 CONFIG_SERIAL_8250_EXTENDED=y @@ -1610,7 +1638,6 @@ CONFIG_SERIAL_8250_EXTENDED=y # CONFIG_SERIAL_8250_SHARE_IRQ is not set # CONFIG_SERIAL_8250_DETECT_IRQ is not set # CONFIG_SERIAL_8250_RSA is not set -CONFIG_SERIAL_8250_SUNXI=y # # Non-8250 serial port support @@ -1626,7 +1653,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_ALTERA_UART is not set # CONFIG_SERIAL_IFX6X60 is not set # CONFIG_SERIAL_XILINX_PS_UART is not set -# CONFIG_SERIAL_SW is not set # CONFIG_TTY_PRINTK is not set # CONFIG_HVC_DCC is not set # CONFIG_IPMI_HANDLER is not set @@ -1636,12 +1662,7 @@ CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_TCG_TPM is not set # CONFIG_DCC_TTY is not set # CONFIG_RAMOOPS is not set -# CONFIG_DMA_TEST_DRIVER is not set -# CONFIG_SUN7I_GPIO_TEST is not set -# CONFIG_SUN7I_G2D is not set -# CONFIG_SUNXI_TIMER_TEST is not set -CONFIG_SUNXI_PHYS_MEM_ALLOCATOR=y -# CONFIG_SUNXI_MEM_TEST is not set +CONFIG_SUNXI_G2D=y CONFIG_I2C=y CONFIG_I2C_BOARDINFO=y CONFIG_I2C_COMPAT=y @@ -1662,8 +1683,8 @@ CONFIG_I2C_HELPER_AUTO=y # CONFIG_I2C_PCA_PLATFORM is not set # CONFIG_I2C_PXA_PCI is not set # CONFIG_I2C_SIMTEC is not set -CONFIG_I2C_SUN7I=y -# CONFIG_SUN7I_I2C_PRINT_TRANSFER_INFO is not set +CONFIG_I2C_SUNXI=y +# CONFIG_SUNXI_IIC_PRINT_TRANSFER_INFO is not set # CONFIG_I2C_XILINX is not set # @@ -1694,9 +1715,6 @@ CONFIG_SPI_MASTER=y # CONFIG_SPI_OC_TINY is not set # CONFIG_SPI_PL022 is not set # CONFIG_SPI_PXA2XX_PCI is not set -CONFIG_SPI_SUN7I=y -# CONFIG_SUN7I_SPI_NDMA is not set -CONFIG_SUN7I_SPI_NORFLASH=y # CONFIG_SPI_XILINX is not set # CONFIG_SPI_DESIGNWARE is not set @@ -1705,6 +1723,7 @@ CONFIG_SUN7I_SPI_NORFLASH=y # # CONFIG_SPI_SPIDEV is not set # CONFIG_SPI_TLE62X0 is not set +# CONFIG_HSI is not set # # PPS support @@ -1722,7 +1741,7 @@ CONFIG_SUN7I_SPI_NORFLASH=y # # Enable Device Drivers -> PPS to see the PTP clock options. # -CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y CONFIG_GPIOLIB=y # CONFIG_DEBUG_GPIO is not set CONFIG_GPIO_SYSFS=y @@ -1733,6 +1752,7 @@ CONFIG_GPIO_GENERIC=y # CONFIG_GPIO_GENERIC_PLATFORM=y # CONFIG_GPIO_PL061 is not set +CONFIG_GPIO_SUNXI=y # # I2C GPIO expanders: @@ -1783,6 +1803,7 @@ CONFIG_W1_SLAVE_DS2423=m # CONFIG_W1_SLAVE_DS2433 is not set # CONFIG_W1_SLAVE_DS2760 is not set # CONFIG_W1_SLAVE_DS2780 is not set +# CONFIG_W1_SLAVE_DS2781 is not set # CONFIG_W1_SLAVE_BQ27000 is not set CONFIG_POWER_SUPPLY=y CONFIG_AW_AXP=y @@ -1791,12 +1812,12 @@ CONFIG_AW_AXP=y CONFIG_AW_AXP20=y CONFIG_AXP_CHARGEINIT=y CONFIG_AXP_CHGCHANGE=y -CONFIG_AW_AXP20_COU=y -# CONFIG_AW_AXP20_OCV is not set # CONFIG_POWER_SUPPLY_DEBUG is not set +# CONFIG_AXP152 is not set # CONFIG_PDA_POWER is not set # CONFIG_TEST_POWER is not set # CONFIG_BATTERY_DS2780 is not set +# CONFIG_BATTERY_DS2781 is not set # CONFIG_BATTERY_DS2782 is not set # CONFIG_BATTERY_SBS is not set # CONFIG_BATTERY_BQ27x00 is not set @@ -1806,6 +1827,7 @@ CONFIG_AW_AXP20_COU=y # CONFIG_CHARGER_LP8727 is not set # CONFIG_CHARGER_GPIO is not set # CONFIG_CHARGER_MANAGER is not set +# CONFIG_CHARGER_SMB347 is not set CONFIG_HWMON=y # CONFIG_HWMON_VID is not set # CONFIG_HWMON_DEBUG_CHIP is not set @@ -1814,10 +1836,6 @@ CONFIG_HWMON=y # Native drivers # CONFIG_SENSORS_MMA7660=m -CONFIG_SENSORS_MMA865x=m -CONFIG_SENSORS_MMA8452=m -CONFIG_SENSORS_AFA750=m -CONFIG_SENSORS_KIONIX_ACCEL=m # CONFIG_SENSORS_AD7314 is not set # CONFIG_SENSORS_AD7414 is not set # CONFIG_SENSORS_AD7418 is not set @@ -1872,6 +1890,7 @@ CONFIG_SENSORS_KIONIX_ACCEL=m # CONFIG_SENSORS_MAX6639 is not set # CONFIG_SENSORS_MAX6642 is not set # CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_MCP3021 is not set # CONFIG_SENSORS_NTC_THERMISTOR is not set # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_PC87427 is not set @@ -1921,7 +1940,6 @@ CONFIG_WATCHDOG=y # CONFIG_DW_WATCHDOG is not set # CONFIG_MPCORE_WATCHDOG is not set # CONFIG_MAX63XX_WATCHDOG is not set -CONFIG_SUNXI_WDT=y # # USB-based Watchdog Cards @@ -1953,11 +1971,13 @@ CONFIG_BCMA_POSSIBLE=y # CONFIG_TPS6105X is not set # CONFIG_TPS65010 is not set # CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65217 is not set # CONFIG_MFD_TPS6586X is not set # CONFIG_MFD_TPS65910 is not set # CONFIG_MFD_TPS65912_I2C is not set # CONFIG_MFD_TPS65912_SPI is not set # CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set # CONFIG_MFD_STMPE is not set # CONFIG_MFD_TC3589X is not set # CONFIG_MFD_TMIO is not set @@ -1982,7 +2002,9 @@ CONFIG_BCMA_POSSIBLE=y # CONFIG_ABX500_CORE is not set # CONFIG_EZX_PCAP is not set # CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_TPS65090 is not set # CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_MFD_RC5T583 is not set CONFIG_REGULATOR=y # CONFIG_REGULATOR_DEBUG is not set # CONFIG_REGULATOR_DUMMY is not set @@ -1990,17 +2012,17 @@ CONFIG_REGULATOR=y # CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set # CONFIG_REGULATOR_USERSPACE_CONSUMER is not set # CONFIG_REGULATOR_GPIO is not set -# CONFIG_REGULATOR_BQ24022 is not set +# CONFIG_REGULATOR_AD5398 is not set +# CONFIG_REGULATOR_ISL6271A is not set # CONFIG_REGULATOR_MAX1586 is not set # CONFIG_REGULATOR_MAX8649 is not set # CONFIG_REGULATOR_MAX8660 is not set # CONFIG_REGULATOR_MAX8952 is not set # CONFIG_REGULATOR_LP3971 is not set # CONFIG_REGULATOR_LP3972 is not set +# CONFIG_REGULATOR_TPS62360 is not set # CONFIG_REGULATOR_TPS65023 is not set # CONFIG_REGULATOR_TPS6507X is not set -# CONFIG_REGULATOR_ISL6271A is not set -# CONFIG_REGULATOR_AD5398 is not set # CONFIG_REGULATOR_TPS6524X is not set CONFIG_MEDIA_SUPPORT=y @@ -2036,6 +2058,7 @@ CONFIG_IR_MCEUSB=m CONFIG_IR_REDRAT3=m CONFIG_IR_STREAMZAP=m CONFIG_RC_LOOPBACK=m +# CONFIG_IR_GPIO_CIR is not set # CONFIG_MEDIA_ATTACH is not set CONFIG_MEDIA_TUNER=m # CONFIG_MEDIA_TUNER_CUSTOMISE is not set @@ -2062,7 +2085,6 @@ CONFIG_MEDIA_TUNER_TDA18212=m CONFIG_VIDEO_V4L2=m CONFIG_VIDEOBUF_GEN=m CONFIG_VIDEOBUF_VMALLOC=m -CONFIG_VIDEOBUF_DMA_CONTIG=m CONFIG_VIDEOBUF_DVB=m CONFIG_VIDEO_TVEEPROM=m CONFIG_VIDEO_TUNER=m @@ -2104,6 +2126,7 @@ CONFIG_VIDEO_WM8775=m # Video decoders # # CONFIG_VIDEO_ADV7180 is not set +# CONFIG_VIDEO_ADV7183 is not set # CONFIG_VIDEO_BT819 is not set # CONFIG_VIDEO_BT856 is not set # CONFIG_VIDEO_BT866 is not set @@ -2141,6 +2164,7 @@ CONFIG_VIDEO_CX2341X=m # Camera sensor devices # # CONFIG_VIDEO_OV7670 is not set +# CONFIG_VIDEO_VS6624 is not set # CONFIG_VIDEO_MT9V011 is not set # CONFIG_VIDEO_TCM825X is not set # CONFIG_VIDEO_SR030PC30 is not set @@ -2242,11 +2266,10 @@ CONFIG_USB_STKWEBCAM=m CONFIG_USB_S2255=m # CONFIG_V4L_PLATFORM_DRIVERS is not set # CONFIG_V4L_MEM2MEM_DRIVERS is not set -CONFIG_VIDEO_SUN7I_CEDAR=y -CONFIG_VIDEO_DECODER_SUN7I=y -# CONFIG_VIDEO_CSI_SUNXI is not set -# CONFIG_AW_TSC is not set -CONFIG_SUN7I_TVD=m +CONFIG_VIDEO_SUNXI_CEDAR=y +CONFIG_VIDEO_DECODER_SUNXI=y +# CONFIG_VIDEO_AVS_COUNTER is not set +# CONFIG_VIDEO_CSI_SUN4I is not set CONFIG_RADIO_ADAPTERS=y CONFIG_RADIO_SI470X=y CONFIG_USB_SI470X=m @@ -2255,6 +2278,7 @@ CONFIG_USB_MR800=m CONFIG_USB_DSBR=m # CONFIG_I2C_SI4713 is not set # CONFIG_RADIO_SI4713 is not set +# CONFIG_USB_KEENE is not set # CONFIG_RADIO_TEA5764 is not set # CONFIG_RADIO_SAA7706H is not set # CONFIG_RADIO_TEF6862 is not set @@ -2264,6 +2288,8 @@ CONFIG_USB_DSBR=m # Texas Instruments WL128x FM driver (ST based) # CONFIG_RADIO_WL128X=m +CONFIG_AUDIO_ENGINE=y +CONFIG_ACE_CONFIG=y # CONFIG_PA_CONTROL is not set CONFIG_DVB_MAX_ADAPTERS=8 # CONFIG_DVB_DYNAMIC_MINORS is not set @@ -2304,11 +2330,13 @@ CONFIG_DVB_USB_AF9015=m CONFIG_DVB_USB_CE6230=m CONFIG_DVB_USB_FRIIO=m CONFIG_DVB_USB_EC168=m +# CONFIG_DVB_USB_AZ6007 is not set CONFIG_DVB_USB_AZ6027=m CONFIG_DVB_USB_LME2510=m CONFIG_DVB_USB_TECHNISAT_USB2=m CONFIG_DVB_USB_IT913X=m CONFIG_DVB_USB_MXL111SF=m +# CONFIG_DVB_USB_RTL28XXU is not set CONFIG_SMS_SIANO_MDTV=m # @@ -2400,6 +2428,7 @@ CONFIG_DVB_EC100=m CONFIG_DVB_HD29L2=m CONFIG_DVB_STV0367=m CONFIG_DVB_CXD2820R=m +CONFIG_DVB_RTL2830=m # # DVB-C (cable) frontends @@ -2451,6 +2480,7 @@ CONFIG_DVB_ATBM8830=m CONFIG_DVB_TDA665x=m CONFIG_DVB_IX2505V=m CONFIG_DVB_IT913X_FE=m +CONFIG_DVB_M88RS2000=m # # Tools to develop new frontends @@ -2462,15 +2492,21 @@ CONFIG_DVB_IT913X_FE=m # # CONFIG_DRM is not set # CONFIG_ION is not set +CONFIG_MALI=m +CONFIG_MALI400=m +# CONFIG_MALI400_DEBUG is not set +# CONFIG_MALI400_GPU_UTILIZATION is not set +CONFIG_UMP=m +# CONFIG_UMP_DEBUG is not set # CONFIG_VGASTATE is not set CONFIG_VIDEO_OUTPUT_CONTROL=y CONFIG_FB=y # CONFIG_FIRMWARE_EDID is not set # CONFIG_FB_DDC is not set # CONFIG_FB_BOOT_VESA_SUPPORT is not set -CONFIG_FB_CFB_FILLRECT=y -CONFIG_FB_CFB_COPYAREA=y -CONFIG_FB_CFB_IMAGEBLIT=y +CONFIG_FB_CFB_FILLRECT=m +CONFIG_FB_CFB_COPYAREA=m +CONFIG_FB_CFB_IMAGEBLIT=m # CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set CONFIG_FB_SYS_FILLRECT=m CONFIG_FB_SYS_COPYAREA=m @@ -2488,9 +2524,12 @@ CONFIG_FB_MODE_HELPERS=y # # Frame buffer hardware drivers # -CONFIG_LYCHEE_FB_SUN7I=y -CONFIG_LYCHEE_LCD_SUN7I=y -CONFIG_LYCHEE_HDMI_SUN7I=y +CONFIG_FB_SUNXI=m +CONFIG_FB_SUNXI_RESERVED_MEM=y +CONFIG_FB_SUNXI_UMP=y +CONFIG_FB_SUNXI_LCD=m +CONFIG_FB_SUNXI_HDMI=m +# CONFIG_HDMI_CEC is not set # CONFIG_FB_ARMCLCD is not set # CONFIG_FB_S1D13XXX is not set # CONFIG_FB_SMSCUFX is not set @@ -2498,6 +2537,7 @@ CONFIG_FB_UDL=m # CONFIG_FB_VIRTUAL is not set # CONFIG_FB_METRONOME is not set # CONFIG_FB_BROADSHEET is not set +# CONFIG_EXYNOS_VIDEO is not set CONFIG_BACKLIGHT_LCD_SUPPORT=y CONFIG_LCD_CLASS_DEVICE=m # CONFIG_LCD_L4F00242T03 is not set @@ -2513,6 +2553,7 @@ CONFIG_BACKLIGHT_CLASS_DEVICE=m CONFIG_BACKLIGHT_GENERIC=m # CONFIG_BACKLIGHT_ADP8860 is not set # CONFIG_BACKLIGHT_ADP8870 is not set +# CONFIG_BACKLIGHT_LP855X is not set # # Console display driver support @@ -2551,6 +2592,7 @@ CONFIG_SND_SUPPORT_OLD_API=y CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_VERBOSE_PRINTK is not set # CONFIG_SND_DEBUG is not set +CONFIG_SND_VMASTER=y CONFIG_SND_RAWMIDI_SEQ=m # CONFIG_SND_OPL3_LIB_SEQ is not set # CONFIG_SND_OPL4_LIB_SEQ is not set @@ -2573,16 +2615,16 @@ CONFIG_SND_USB_CAIAQ=m CONFIG_SND_USB_CAIAQ_INPUT=y CONFIG_SND_USB_6FIRE=m CONFIG_SND_SOC=y -CONFIG_SND_SUN7I_SOC_CODEC=y -CONFIG_SND_SUN7I_SOC_HDMIAUDIO=y -CONFIG_SND_SUN7I_SOC_SPDIF=y -CONFIG_SND_SUN7I_SOC_I2S_INTERFACE=y +CONFIG_SOUND_SUNXI=y +CONFIG_SND_SUNXI_SOC_CODEC=y +CONFIG_SND_SUNXI_SOC_HDMIAUDIO=y +CONFIG_SND_SUNXI_SOC_SPDIF=m CONFIG_SND_SOC_I2C_AND_SPI=y # CONFIG_SND_SOC_ALL_CODECS is not set # CONFIG_SOUND_PRIME is not set CONFIG_HID_SUPPORT=y CONFIG_HID=y -CONFIG_HID_BATTERY_STRENGTH=y +# CONFIG_HID_BATTERY_STRENGTH is not set CONFIG_HIDRAW=y # CONFIG_UHID is not set @@ -2642,13 +2684,7 @@ CONFIG_HID_PICOLCD_FB=y CONFIG_HID_PICOLCD_LEDS=y CONFIG_HID_PRIMAX=m CONFIG_HID_ROCCAT=m -CONFIG_HID_ROCCAT_COMMON=m -CONFIG_HID_ROCCAT_ARVO=m -CONFIG_HID_ROCCAT_ISKU=m -CONFIG_HID_ROCCAT_KONE=m -CONFIG_HID_ROCCAT_KONEPLUS=m -CONFIG_HID_ROCCAT_KOVAPLUS=m -CONFIG_HID_ROCCAT_PYRA=m +# CONFIG_HID_SAITEK is not set CONFIG_HID_SAMSUNG=m CONFIG_HID_SONY=m CONFIG_HID_SPEEDLINK=m @@ -2657,6 +2693,7 @@ CONFIG_HID_GREENASIA=m CONFIG_GREENASIA_FF=y CONFIG_HID_SMARTJOYPLUS=m CONFIG_SMARTJOYPLUS_FF=y +# CONFIG_HID_TIVO is not set CONFIG_HID_TOPSEED=m CONFIG_HID_THRUSTMASTER=m CONFIG_THRUSTMASTER_FF=y @@ -2665,12 +2702,12 @@ CONFIG_THRUSTMASTER_FF=y CONFIG_HID_ZEROPLUS=m CONFIG_ZEROPLUS_FF=y CONFIG_HID_ZYDACRON=m -CONFIG_USB_SUPPORT=y -CONFIG_USB_COMMON=y -CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y CONFIG_USB_ARCH_HAS_EHCI=y # CONFIG_USB_ARCH_HAS_XHCI is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_COMMON=y +CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB=y # CONFIG_USB_DEBUG is not set # CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set @@ -2694,25 +2731,22 @@ CONFIG_USB_DEVICE_CLASS=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_ROOT_HUB_TT=y CONFIG_USB_EHCI_TT_NEWSCHED=y -# CONFIG_USB_EHCI_MV is not set # CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP1760_HCD is not set # CONFIG_USB_ISP1362_HCD is not set CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_HCD_PLATFORM is not set +# CONFIG_USB_EHCI_HCD_PLATFORM is not set # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set CONFIG_USB_OHCI_LITTLE_ENDIAN=y # CONFIG_USB_U132_HCD is not set # CONFIG_USB_SL811_HCD is not set # CONFIG_USB_R8A66597_HCD is not set -CONFIG_USB_SW_SUN7I_HCD=y -CONFIG_USB_SW_SUN7I_HCD0=y -CONFIG_USB_SW_SUN7I_HCI=y -CONFIG_USB_SW_SUN7I_EHCI0=y -CONFIG_USB_SW_SUN7I_EHCI1=y -CONFIG_USB_SW_SUN7I_OHCI0=y -CONFIG_USB_SW_SUN7I_OHCI1=y +CONFIG_USB_SUNXI_EHCI=y +CONFIG_USB_SUNXI_OHCI=y +CONFIG_USB_SUNXI_COMMON=y # CONFIG_USB_MUSB_HDRC is not set # CONFIG_USB_RENESAS_USBHS is not set @@ -2746,7 +2780,6 @@ CONFIG_USB_STORAGE_ONETOUCH=m CONFIG_USB_STORAGE_KARMA=m CONFIG_USB_STORAGE_CYPRESS_ATACB=m CONFIG_USB_STORAGE_ENE_UB6250=m -CONFIG_USB_UAS=m CONFIG_USB_LIBUSUAL=y # @@ -2778,6 +2811,7 @@ CONFIG_USB_SERIAL_FTDI_SIO=m # CONFIG_USB_SERIAL_IR is not set # CONFIG_USB_SERIAL_EDGEPORT is not set # CONFIG_USB_SERIAL_EDGEPORT_TI is not set +# CONFIG_USB_SERIAL_F81232 is not set # CONFIG_USB_SERIAL_GARMIN is not set # CONFIG_USB_SERIAL_IPW is not set # CONFIG_USB_SERIAL_IUU is not set @@ -2786,6 +2820,7 @@ CONFIG_USB_SERIAL_FTDI_SIO=m # CONFIG_USB_SERIAL_KLSI is not set # CONFIG_USB_SERIAL_KOBIL_SCT is not set # CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_METRO is not set # CONFIG_USB_SERIAL_MOS7720 is not set # CONFIG_USB_SERIAL_MOS7840 is not set # CONFIG_USB_SERIAL_MOTOROLA is not set @@ -2842,10 +2877,15 @@ CONFIG_USB_GADGET=y # CONFIG_USB_GADGET_DEBUG_FS is not set CONFIG_USB_GADGET_VBUS_DRAW=2 CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 -CONFIG_USB_SW_SUN7I_UDC0=y -CONFIG_USB_GADGET_DUALSPEED=y +# CONFIG_USB_FUSB300 is not set +# CONFIG_USB_R8A66597 is not set +# CONFIG_USB_MV_UDC is not set +# CONFIG_USB_M66592 is not set +# CONFIG_USB_NET2272 is not set +# CONFIG_USB_DUMMY_HCD is not set # CONFIG_USB_ZERO is not set CONFIG_USB_AUDIO=m +# CONFIG_GADGET_UAC1 is not set CONFIG_USB_ETH=m CONFIG_USB_ETH_RNDIS=y CONFIG_USB_ETH_EEM=y @@ -2871,13 +2911,7 @@ CONFIG_USB_G_WEBCAM=m # CONFIG_USB_GPIO_VBUS is not set # CONFIG_USB_ULPI is not set # CONFIG_NOP_USB_XCEIV is not set -CONFIG_USB_SW_SUN7I_USB=y -CONFIG_USB_SW_SUN7I_USB_MANAGER=y -# CONFIG_USB_SW_SUN7I_USB0_NULL is not set -# CONFIG_USB_SW_SUN7I_USB0_DEVICE_ONLY is not set -# CONFIG_USB_SW_SUN7I_USB0_HOST_ONLY is not set -CONFIG_USB_SW_SUN7I_USB0_OTG=y -CONFIG_USB_SW_SUN7I_USB_DEBUG=y +# CONFIG_USB_SW_SUNXI_USB is not set CONFIG_MMC=y # CONFIG_MMC_DEBUG is not set CONFIG_MMC_UNSAFE_RESUME=y @@ -2903,11 +2937,20 @@ CONFIG_MMC_BLOCK_MINORS=16 # CONFIG_MMC_SDHCI_PXAV3 is not set # CONFIG_MMC_SDHCI_PXAV2 is not set # CONFIG_MMC_DW is not set -CONFIG_MMC_SUN7I=y +CONFIG_MMC_SUNXI_NEW=y # CONFIG_MMC_DEBUG_SUNXI is not set CONFIG_MMC_PRE_DBGLVL_SUNXI=3 # CONFIG_MMC_VUB300 is not set -# CONFIG_MMC_USHC is not set +CONFIG_MMC_USHC=m + +# +# MMC/SD/SDIO Card Power Management Drivers +# +CONFIG_MMC_SUNXI_POWER_CONTROL=y + +# +# SUNXI MMC/SD/SDIO Host Controller Drivers +# # CONFIG_MEMSTICK is not set CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y @@ -2923,6 +2966,7 @@ CONFIG_LEDS_SUNXI=y # CONFIG_LEDS_LP5521 is not set # CONFIG_LEDS_LP5523 is not set # CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_PCA9633 is not set # CONFIG_LEDS_DAC124S085 is not set # CONFIG_LEDS_REGULATOR is not set # CONFIG_LEDS_BD2802 is not set @@ -2938,13 +2982,14 @@ CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=y CONFIG_LEDS_TRIGGER_HEARTBEAT=y CONFIG_LEDS_TRIGGER_BACKLIGHT=y +CONFIG_LEDS_TRIGGER_CPU=y CONFIG_LEDS_TRIGGER_GPIO=y CONFIG_LEDS_TRIGGER_DEFAULT_ON=y -CONFIG_LEDS_TRIGGER_SLEEP=y # # iptables trigger is under Netfilter config (LED target) # +# CONFIG_SWITCH is not set # CONFIG_ACCESSIBILITY is not set CONFIG_RTC_LIB=y CONFIG_RTC_CLASS=y @@ -2959,10 +3004,6 @@ CONFIG_RTC_INTF_SYSFS=y CONFIG_RTC_INTF_PROC=y CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_INTF_DEV_UIE_EMUL is not set -CONFIG_RTC_INTF_ALARM=y -CONFIG_RTC_INTF_ALARM_DEV=y -# CONFIG_RTC_ALARM_CLOCK_WAKEUP is not set -# CONFIG_RTC_ALARM_SHUTDOWN_WAKEUP is not set # CONFIG_RTC_DRV_TEST is not set # @@ -3023,9 +3064,9 @@ CONFIG_RTC_INTF_ALARM_DEV=y # # CONFIG_RTC_DRV_PL030 is not set # CONFIG_RTC_DRV_PL031 is not set -CONFIG_RTC_DRV_SUN7I=y +# CONFIG_RTC_DRV_SUN4I is not set # CONFIG_DMADEVICES is not set -# CONFIG_AUXDISPLAY is not set +CONFIG_AUXDISPLAY=y # CONFIG_UIO is not set # @@ -3056,8 +3097,6 @@ CONFIG_RTS5139=m # CONFIG_USB_SERIAL_QUATECH_USB2 is not set # CONFIG_VT6656 is not set # CONFIG_IIO is not set -# CONFIG_XVMALLOC is not set -# CONFIG_ZRAM is not set # CONFIG_FB_SM7XX is not set # CONFIG_USB_ENESTORAGE is not set # CONFIG_BCM_WIMAX is not set @@ -3095,24 +3134,27 @@ CONFIG_ANDROID_TIMED_OUTPUT=y # CONFIG_ANDROID_TIMED_GPIO is not set # CONFIG_ANDROID_LOW_MEMORY_KILLER is not set CONFIG_ANDROID_SWITCH=y -CONFIG_SWITCH_HEADSET=y CONFIG_ANDROID_SWITCH_GPIO=y +# CONFIG_ANDROID_INTF_ALARM_DEV is not set +# CONFIG_PHONE is not set +# CONFIG_USB_WPAN_HCD is not set CONFIG_CLKDEV_LOOKUP=y -CONFIG_HAVE_MACH_CLKDEV=y # # Hardware Spinlock drivers # # CONFIG_IOMMU_SUPPORT is not set -# CONFIG_VIRT_DRIVERS is not set -# CONFIG_PM_DEVFREQ is not set -# CONFIG_GSENSOR is not set -# CONFIG_NEW_GPIO is not set # -# gpu +# Remoteproc drivers (EXPERIMENTAL) # +# +# Rpmsg drivers (EXPERIMENTAL) +# +# CONFIG_VIRT_DRIVERS is not set +# CONFIG_PM_DEVFREQ is not set + # # File systems # @@ -3216,6 +3258,7 @@ CONFIG_CRAMFS=y # CONFIG_OMFS_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set +# CONFIG_QNX6FS_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_PSTORE is not set # CONFIG_SYSV_FS is not set @@ -3228,11 +3271,11 @@ CONFIG_NFS_V4=y CONFIG_NFS_V4_1=y CONFIG_PNFS_FILE_LAYOUT=y CONFIG_PNFS_BLOCK=m +CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="kernel.org" CONFIG_ROOT_NFS=y CONFIG_NFS_FSCACHE=y # CONFIG_NFS_USE_LEGACY_DNS is not set CONFIG_NFS_USE_KERNEL_DNS=y -# CONFIG_NFS_USE_NEW_IDMAPPER is not set CONFIG_NFSD=m CONFIG_NFSD_V2_ACL=y CONFIG_NFSD_V3=y @@ -3246,6 +3289,7 @@ CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y CONFIG_SUNRPC_GSS=y CONFIG_SUNRPC_BACKCHANNEL=y +# CONFIG_SUNRPC_DEBUG is not set # CONFIG_CEPH_FS is not set CONFIG_CIFS=m # CONFIG_CIFS_STATS is not set @@ -3319,6 +3363,8 @@ CONFIG_DEBUG_FS=y CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_SHIRQ is not set # CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_HARDLOCKUP_DETECTOR_NMI is not set +# CONFIG_HARDLOCKUP_DETECTOR_OTHER_CPU is not set # CONFIG_HARDLOCKUP_DETECTOR is not set # CONFIG_DETECT_HUNG_TASK is not set # CONFIG_SCHED_DEBUG is not set @@ -3357,6 +3403,8 @@ CONFIG_DEBUG_LIST=y # CONFIG_RCU_TORTURE_TEST is not set CONFIG_RCU_CPU_STALL_TIMEOUT=60 CONFIG_RCU_CPU_STALL_VERBOSE=y +# CONFIG_RCU_CPU_STALL_INFO is not set +# CONFIG_RCU_TRACE is not set # CONFIG_BACKTRACE_SELF_TEST is not set # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set @@ -3364,7 +3412,6 @@ CONFIG_RCU_CPU_STALL_VERBOSE=y # CONFIG_LKDTM is not set # CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set # CONFIG_FAULT_INJECTION is not set -# CONFIG_SYSCTL_SYSCALL_CHECK is not set CONFIG_DEBUG_PAGEALLOC=y CONFIG_WANT_PAGE_DEBUG_FLAGS=y CONFIG_PAGE_POISONING=y @@ -3390,9 +3437,9 @@ CONFIG_ARM_UNWIND=y CONFIG_DEBUG_USER=y # CONFIG_DEBUG_RODATA is not set CONFIG_DEBUG_LL=y -# CONFIG_DEBUG_LL_UART_NONE is not set +CONFIG_DEBUG_LL_UART_NONE=y # CONFIG_DEBUG_ICEDCC is not set -CONFIG_DEBUG_AW_UART0=y +# CONFIG_DEBUG_SEMIHOSTING is not set CONFIG_EARLY_PRINTK=y # CONFIG_OC_ETM is not set @@ -3526,11 +3573,17 @@ CONFIG_CRYPTO_ANSI_CPRNG=y CONFIG_RAID6_PQ=m CONFIG_BITREVERSE=y CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_IO=y CONFIG_CRC_CCITT=y CONFIG_CRC16=y CONFIG_CRC_T10DIF=y CONFIG_CRC_ITU_T=y CONFIG_CRC32=y +# CONFIG_CRC32_SELFTEST is not set +CONFIG_CRC32_SLICEBY8=y +# CONFIG_CRC32_SLICEBY4 is not set +# CONFIG_CRC32_SARWATE is not set +# CONFIG_CRC32_BIT is not set # CONFIG_CRC7 is not set CONFIG_LIBCRC32C=m # CONFIG_CRC8 is not set diff --git a/core/linux-sun7i/linux-sun7i.install b/core/linux-sun7i/linux-sun7i.install index 0d1ba5e5d..eaab6363c 100644 --- a/core/linux-sun7i/linux-sun7i.install +++ b/core/linux-sun7i/linux-sun7i.install @@ -2,7 +2,7 @@ # arg 2: the old package version KERNEL_NAME=-sun7i -KERNEL_VERSION=3.3.0-3-ARCH +KERNEL_VERSION=3.4.79-1-ARCH post_install () { # updating module dependencies diff --git a/core/linux-sun7i/memset.patch b/core/linux-sun7i/memset.patch deleted file mode 100644 index a741741ab..000000000 --- a/core/linux-sun7i/memset.patch +++ /dev/null @@ -1,204 +0,0 @@ ---- a/arch/arm/lib/memset.S -+++ b/arch/arm/lib/memset.S -@@ -19,9 +19,9 @@ - 1: subs r2, r2, #4 @ 1 do we have enough - blt 5f @ 1 bytes to align with? - cmp r3, #2 @ 1 -- strltb r1, [r0], #1 @ 1 -- strleb r1, [r0], #1 @ 1 -- strb r1, [r0], #1 @ 1 -+ strltb r1, [ip], #1 @ 1 -+ strleb r1, [ip], #1 @ 1 -+ strb r1, [ip], #1 @ 1 - add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3)) - /* - * The pointer is now aligned and the length is adjusted. Try doing the -@@ -29,10 +29,14 @@ - */ - - ENTRY(memset) -- ands r3, r0, #3 @ 1 unaligned? -+/* -+ * Preserve the contents of r0 for the return value. -+ */ -+ mov ip, r0 -+ ands r3, ip, #3 @ 1 unaligned? - bne 1b @ 1 - /* -- * we know that the pointer in r0 is aligned to a word boundary. -+ * we know that the pointer in ip is aligned to a word boundary. - */ - orr r1, r1, r1, lsl #8 - orr r1, r1, r1, lsl #16 -@@ -43,29 +47,28 @@ ENTRY(memset) - #if ! CALGN(1)+0 - - /* -- * We need an extra register for this loop - save the return address and -- * use the LR -+ * We need 2 extra registers for this loop - use r8 and the LR - */ -- str lr, [sp, #-4]! -- mov ip, r1 -+ stmfd sp!, {r8, lr} -+ mov r8, r1 - mov lr, r1 - - 2: subs r2, r2, #64 -- stmgeia r0!, {r1, r3, ip, lr} @ 64 bytes at a time. -- stmgeia r0!, {r1, r3, ip, lr} -- stmgeia r0!, {r1, r3, ip, lr} -- stmgeia r0!, {r1, r3, ip, lr} -+ stmgeia ip!, {r1, r3, r8, lr} @ 64 bytes at a time. -+ stmgeia ip!, {r1, r3, r8, lr} -+ stmgeia ip!, {r1, r3, r8, lr} -+ stmgeia ip!, {r1, r3, r8, lr} - bgt 2b -- ldmeqfd sp!, {pc} @ Now <64 bytes to go. -+ ldmeqfd sp!, {r8, pc} @ Now <64 bytes to go. - /* - * No need to correct the count; we're only testing bits from now on - */ - tst r2, #32 -- stmneia r0!, {r1, r3, ip, lr} -- stmneia r0!, {r1, r3, ip, lr} -+ stmneia ip!, {r1, r3, r8, lr} -+ stmneia ip!, {r1, r3, r8, lr} - tst r2, #16 -- stmneia r0!, {r1, r3, ip, lr} -- ldr lr, [sp], #4 -+ stmneia ip!, {r1, r3, r8, lr} -+ ldmfd sp!, {r8, lr} - - #else - -@@ -74,54 +77,54 @@ ENTRY(memset) - * whole cache lines at once. - */ - -- stmfd sp!, {r4-r7, lr} -+ stmfd sp!, {r4-r8, lr} - mov r4, r1 - mov r5, r1 - mov r6, r1 - mov r7, r1 -- mov ip, r1 -+ mov r8, r1 - mov lr, r1 - - cmp r2, #96 -- tstgt r0, #31 -+ tstgt ip, #31 - ble 3f - -- and ip, r0, #31 -- rsb ip, ip, #32 -- sub r2, r2, ip -- movs ip, ip, lsl #(32 - 4) -- stmcsia r0!, {r4, r5, r6, r7} -- stmmiia r0!, {r4, r5} -- tst ip, #(1 << 30) -- mov ip, r1 -- strne r1, [r0], #4 -+ and r8, ip, #31 -+ rsb r8, r8, #32 -+ sub r2, r2, r8 -+ movs r8, r8, lsl #(32 - 4) -+ stmcsia ip!, {r4, r5, r6, r7} -+ stmmiia ip!, {r4, r5} -+ tst r8, #(1 << 30) -+ mov r8, r1 -+ strne r1, [ip], #4 - - 3: subs r2, r2, #64 -- stmgeia r0!, {r1, r3-r7, ip, lr} -- stmgeia r0!, {r1, r3-r7, ip, lr} -+ stmgeia ip!, {r1, r3-r8, lr} -+ stmgeia ip!, {r1, r3-r8, lr} - bgt 3b -- ldmeqfd sp!, {r4-r7, pc} -+ ldmeqfd sp!, {r4-r8, pc} - - tst r2, #32 -- stmneia r0!, {r1, r3-r7, ip, lr} -+ stmneia ip!, {r1, r3-r8, lr} - tst r2, #16 -- stmneia r0!, {r4-r7} -- ldmfd sp!, {r4-r7, lr} -+ stmneia ip!, {r4-r7} -+ ldmfd sp!, {r4-r8, lr} - - #endif - - 4: tst r2, #8 -- stmneia r0!, {r1, r3} -+ stmneia ip!, {r1, r3} - tst r2, #4 -- strne r1, [r0], #4 -+ strne r1, [ip], #4 - /* - * When we get here, we've got less than 4 bytes to zero. We - * may have an unaligned pointer as well. - */ - 5: tst r2, #2 -- strneb r1, [r0], #1 -- strneb r1, [r0], #1 -+ strneb r1, [ip], #1 -+ strneb r1, [ip], #1 - tst r2, #1 -- strneb r1, [r0], #1 -+ strneb r1, [ip], #1 - mov pc, lr - ENDPROC(memset) ---- a/arch/arm/lib/memset.S -+++ b/arch/arm/lib/memset.S -@@ -14,31 +14,15 @@ - - .text - .align 5 -- .word 0 -- --1: subs r2, r2, #4 @ 1 do we have enough -- blt 5f @ 1 bytes to align with? -- cmp r3, #2 @ 1 -- strltb r1, [ip], #1 @ 1 -- strleb r1, [ip], #1 @ 1 -- strb r1, [ip], #1 @ 1 -- add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3)) --/* -- * The pointer is now aligned and the length is adjusted. Try doing the -- * memset again. -- */ - - ENTRY(memset) --/* -- * Preserve the contents of r0 for the return value. -- */ -- mov ip, r0 -- ands r3, ip, #3 @ 1 unaligned? -- bne 1b @ 1 -+ ands r3, r0, #3 @ 1 unaligned? -+ mov ip, r0 @ preserve r0 as return value -+ bne 6f @ 1 - /* - * we know that the pointer in ip is aligned to a word boundary. - */ -- orr r1, r1, r1, lsl #8 -+1: orr r1, r1, r1, lsl #8 - orr r1, r1, r1, lsl #16 - mov r3, r1 - cmp r2, #16 -@@ -127,4 +111,13 @@ ENTRY(memset) - tst r2, #1 - strneb r1, [ip], #1 - mov pc, lr -+ -+6: subs r2, r2, #4 @ 1 do we have enough -+ blt 5b @ 1 bytes to align with? -+ cmp r3, #2 @ 1 -+ strltb r1, [ip], #1 @ 1 -+ strleb r1, [ip], #1 @ 1 -+ strb r1, [ip], #1 @ 1 -+ add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3)) -+ b 1b - ENDPROC(memset) diff --git a/core/linux-sun7i/working-bcmdhd-driver.patch b/core/linux-sun7i/working-bcmdhd-driver.patch new file mode 100644 index 000000000..c5c2ba5e8 --- /dev/null +++ b/core/linux-sun7i/working-bcmdhd-driver.patch @@ -0,0 +1,39416 @@ +diff -rupN linux-sunxi/arch/arm/mach-sun7i/Makefile linux-sunxi-new/arch/arm/mach-sun7i/Makefile +--- linux-sunxi/arch/arm/mach-sun7i/Makefile 2014-01-27 01:30:27.720384985 +0100 ++++ linux-sunxi-new/arch/arm/mach-sun7i/Makefile 2014-02-15 00:44:23.375867879 +0100 +@@ -4,6 +4,7 @@ + + obj-y = clock/ + obj-y += dma/ ++obj-y += rf/ + obj-$(CONFIG_CPU_FREQ) += cpu-freq/ + obj-$(CONFIG_PM) += pm/ + obj-$(CONFIG_AW_TIME_DELAY) += delay.o +diff -rupN linux-sunxi/arch/arm/mach-sun7i/pm/pm_types.h linux-sunxi-new/arch/arm/mach-sun7i/pm/pm_types.h +--- linux-sunxi/arch/arm/mach-sun7i/pm/pm_types.h 2014-01-27 01:30:27.721385005 +0100 ++++ linux-sunxi-new/arch/arm/mach-sun7i/pm/pm_types.h 2014-02-15 00:44:23.377867923 +0100 +@@ -8,12 +8,20 @@ + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ +- +-#include +- ++ + #ifndef __uxx_sxx_name + #define __uxx_sxx_name ++typedef signed char __s8; ++typedef unsigned char __u8; ++typedef signed short __s16; ++typedef unsigned short __u16; ++typedef signed int __s32; ++typedef unsigned int __u32; ++typedef signed long long __s64; ++typedef unsigned long long __u64; + ++typedef unsigned int size_t; ++//typedef unsigned int ptrdiff_t; + //------------------------------------------------------------------------------ + //return value defines + //------------------------------------------------------------------------------ +@@ -22,6 +30,7 @@ + #define TRUE (1) + #define FALSE (0) + +-#endif + +-#endif /*_PM_TYPES_H*/ ++#endif ++ ++#endif /*_PM_TYPES_H*/ +\ No newline at end of file +diff -rupN linux-sunxi/arch/arm/mach-sun7i/rf/bt_pm.c linux-sunxi-new/arch/arm/mach-sun7i/rf/bt_pm.c +--- linux-sunxi/arch/arm/mach-sun7i/rf/bt_pm.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-sunxi-new/arch/arm/mach-sun7i/rf/bt_pm.c 2014-02-15 00:44:23.376867901 +0100 +@@ -0,0 +1,155 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define RF_MSG(...) do {printk("[rfkill]: "__VA_ARGS__);} while(0) ++ ++#if (defined CONFIG_MMC) ++extern int wifi_pm_get_mod_type(void); ++extern int wifi_pm_gpio_ctrl(char* name, int level); ++#else ++static __inline int wifi_pm_get_mod_type(void) ++{ ++ pr_warning("[%s] not implemented!\n", __FUNCTION__); ++ return 0; ++} ++static __inline int wifi_pm_gpio_ctrl(char* name, int level) ++{ ++ pr_warning("[%s] not implemented!\n", __FUNCTION__); ++ return -1; ++} ++#endif ++ ++static const char bt_name[] = "bcm40183"; ++static struct rfkill *sw_rfkill; ++static int bt_used; ++ ++static int rfkill_set_power(void *data, bool blocked) ++{ ++ unsigned int mod_sel = wifi_pm_get_mod_type(); ++ ++ RF_MSG("rfkill set power %d\n", blocked); ++ ++ switch (mod_sel) ++ { ++ case 2: /* bcm40183 */ ++ if (!blocked) { ++ wifi_pm_gpio_ctrl("bcm40183_bt_regon", 1); ++ wifi_pm_gpio_ctrl("bcm40183_bt_rst", 1); ++ } else { ++ wifi_pm_gpio_ctrl("bcm40183_bt_rst", 0); ++ wifi_pm_gpio_ctrl("bcm40183_bt_regon", 0); ++ } ++ break; ++ case 3: /* realtek rtl8723as */ ++ if (!blocked) { ++ wifi_pm_gpio_ctrl("rtk_rtl8723as_bt_dis", 1); ++ } else { ++ wifi_pm_gpio_ctrl("rtk_rtl8723as_bt_dis", 0); ++ } ++ break; ++ case 7: /* ap6210 */ ++ case 8: /* ap6330 */ ++ if (!blocked) { ++ wifi_pm_gpio_ctrl("ap6xxx_bt_regon", 1); ++ } else { ++ wifi_pm_gpio_ctrl("ap6xxx_bt_regon", 0); ++ } ++ break; ++ case 10: /* realtek rtl8723au */ ++ if (!blocked) { ++ wifi_pm_gpio_ctrl("rtl8723au_bt", 1); ++ } else { ++ wifi_pm_gpio_ctrl("rtl8723au_bt", 0); ++ } ++ break; ++ default: ++ RF_MSG("no bt module matched !!\n"); ++ } ++ ++ msleep(10); ++ return 0; ++} ++ ++static struct rfkill_ops sw_rfkill_ops = { ++ .set_block = rfkill_set_power, ++}; ++ ++static int sw_rfkill_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ sw_rfkill = rfkill_alloc(bt_name, &pdev->dev, ++ RFKILL_TYPE_BLUETOOTH, &sw_rfkill_ops, NULL); ++ if (unlikely(!sw_rfkill)) ++ return -ENOMEM; ++ ++ ret = rfkill_register(sw_rfkill); ++ if (unlikely(ret)) { ++ rfkill_destroy(sw_rfkill); ++ } ++ return ret; ++} ++ ++static int sw_rfkill_remove(struct platform_device *pdev) ++{ ++ if (likely(sw_rfkill)) { ++ rfkill_unregister(sw_rfkill); ++ rfkill_destroy(sw_rfkill); ++ } ++ return 0; ++} ++ ++static struct platform_driver sw_rfkill_driver = { ++ .probe = sw_rfkill_probe, ++ .remove = sw_rfkill_remove, ++ .driver = { ++ .name = "sunxi-rfkill", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static struct platform_device sw_rfkill_dev = { ++ .name = "sunxi-rfkill", ++}; ++ ++static int __init sw_rfkill_init(void) ++{ ++ int type; ++ ++ ++ if (SCRIPT_PARSER_OK != script_parser_fetch("bt_para", "bt_used", &bt_used, 1)) { ++ pr_warning("[PM] parse bt_used failed\n"); ++ return -1; ++ } ++ ++ if (!bt_used) { ++ pr_info("[PM] bt is disable at script fex\n"); ++ return 0; ++ } ++ ++ platform_device_register(&sw_rfkill_dev); ++ return platform_driver_register(&sw_rfkill_driver); ++} ++ ++static void __exit sw_rfkill_exit(void) ++{ ++ if (!bt_used) { ++ pr_info("[PM] exit no bt used in configuration"); ++ return ; ++ } ++ ++ platform_device_unregister(&sw_rfkill_dev); ++ platform_driver_unregister(&sw_rfkill_driver); ++} ++ ++module_init(sw_rfkill_init); ++module_exit(sw_rfkill_exit); ++ ++MODULE_DESCRIPTION("sunxi-rfkill driver"); ++MODULE_AUTHOR("Aaron.magic"); ++MODULE_LICENSE("GPL"); ++ +diff -rupN linux-sunxi/arch/arm/mach-sun7i/rf/Makefile linux-sunxi-new/arch/arm/mach-sun7i/rf/Makefile +--- linux-sunxi/arch/arm/mach-sun7i/rf/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-sunxi-new/arch/arm/mach-sun7i/rf/Makefile 2014-02-15 00:44:23.376867901 +0100 +@@ -0,0 +1,5 @@ ++obj-y += wifi_gpio.o ++wifi_gpio-y := wifi_pm.o wifi_pm_ap6xxx.o ++obj-y += bt_gpio.o ++bt_gpio-y := bt_pm.o ++ +diff -rupN linux-sunxi/arch/arm/mach-sun7i/rf/wifi_pm_ap6xxx.c linux-sunxi-new/arch/arm/mach-sun7i/rf/wifi_pm_ap6xxx.c +--- linux-sunxi/arch/arm/mach-sun7i/rf/wifi_pm_ap6xxx.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-sunxi-new/arch/arm/mach-sun7i/rf/wifi_pm_ap6xxx.c 2014-02-15 00:44:23.376867901 +0100 +@@ -0,0 +1,150 @@ ++/* ++ * ap6xxx sdio wifi power management API ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "wifi_pm.h" ++ ++#define ap6xxx_msg(...) do {printk("[ap6xxx]: "__VA_ARGS__);} while(0) ++ ++static int ap6xxx_wl_regon = 0; ++static int ap6xxx_bt_regon = 0; ++ ++static int ap6xxx_gpio_ctrl(char* name, int level) ++{ ++ int i = 0; ++ int ret = 0; ++ int gpio = 0; ++ char * gpio_name[2] = {"ap6xxx_wl_regon", "ap6xxx_bt_regon"}; ++ ++ for (i = 0; i < 2; i++) { ++ if (strcmp(name, gpio_name[i]) == 0) { ++ switch (i) ++ { ++ case 0: /*ap6xxx_wl_regon*/ ++ gpio = ap6xxx_wl_regon; ++ break; ++ case 1: /*ap6xxx_bt_regon*/ ++ gpio = ap6xxx_bt_regon; ++ break; ++ default: ++ ap6xxx_msg("no matched gpio.\n"); ++ } ++ break; ++ } ++ } ++ ++ ret = gpio_write_one_pin_value(gpio, level, name); ++ ++ return 0; ++} ++ ++static int ap6xxx_gpio_read(char* name) ++{ ++ int i = 0; ++ int gpio = 0; ++ int val = 0; ++ char * gpio_name[2] = {"ap6xxx_wl_regon", "ap6xxx_bt_regon"}; ++ ++ for (i = 0; i < 2; i++) { ++ if (strcmp(name, gpio_name[i]) == 0) { ++ switch (i) ++ { ++ case 0: /*ap6xxx_wl_regon*/ ++ gpio = ap6xxx_wl_regon; ++ break; ++ case 1: /*ap6xxx_bt_regon*/ ++ gpio = ap6xxx_bt_regon; ++ break; ++ default: ++ ap6xxx_msg("no matched gpio.\n"); ++ } ++ break; ++ } ++ } ++ ++ val = gpio_read_one_pin_value(gpio, name); ++ ++ return val; ++} ++ ++ ++void ap6xxx_power(int mode, int *updown) ++{ ++ if (mode) { ++ if (*updown) { ++ ap6xxx_gpio_ctrl("ap6xxx_wl_regon", 1); ++ mdelay(100); ++ } else { ++ ap6xxx_gpio_ctrl("ap6xxx_wl_regon", 0); ++ mdelay(100); ++ } ++ pr_info("sdio wifi power state: %s\n", *updown ? "on" : "off"); ++ } else { ++ *updown = ap6xxx_gpio_read("ap6xxx_wl_regon"); ++ } ++ ++ return; ++} ++ ++static void cfg_gpio_32k_clkout(int gpio_index) ++{ ++ int ret; ++ struct clk *clk_32k, *parent; ++ ++ parent = clk_get(NULL, CLK_SYS_LOSC); ++ clk_32k = clk_get(NULL, CLK_MOD_OUTA); ++ ret = clk_set_parent(clk_32k, parent); ++ ++ if(ret){ ++ pr_err("ap6xxx: 32k clk_set_parent fail\n"); ++ return; ++ } ++ ++ ret = clk_set_rate(clk_32k, 32768); ++ if(ret){ ++ pr_err("ap6xxx: 32k clk_set_rate fail\n"); ++ return; ++ } ++ ++ clk_enable(clk_32k); ++} ++void ap6xxx_gpio_init(void) ++{ ++ struct wifi_pm_ops *ops = &wifi_select_pm_ops; ++ int ap6xxx_lpo = 0; ++ ++/* CT expected ap6xxx_lpo as a GPIO */ ++ ap6xxx_lpo = gpio_request_ex(wifi_para, "ap6xxx_lpo"); ++ if (!ap6xxx_lpo) { ++ pr_err("ap6xxx: request lpo gpio failed\n"); ++ return; ++ } ++ ++ if(ap6xxx_lpo) { ++ pr_info("ap6xxx: config 32k clock\n"); ++ cfg_gpio_32k_clkout(ap6xxx_lpo); ++ } ++ ++ ap6xxx_wl_regon = gpio_request_ex(wifi_para, "ap6xxx_wl_regon"); ++ if (!ap6xxx_wl_regon) { ++ pr_err("ap6xxx: request wl_regon gpio failed\n"); ++ return; ++ } ++ ++ ap6xxx_bt_regon = gpio_request_ex(wifi_para, "ap6xxx_bt_regon"); ++ if (!ap6xxx_bt_regon) { ++ pr_err("ap6xxx: request ap6xxx_bt_regon gpio failed\n"); ++ return; ++ } ++ ++ ops->gpio_ctrl = ap6xxx_gpio_ctrl; ++ ops->power = ap6xxx_power; ++} +diff -rupN linux-sunxi/arch/arm/mach-sun7i/rf/wifi_pm.c linux-sunxi-new/arch/arm/mach-sun7i/rf/wifi_pm.c +--- linux-sunxi/arch/arm/mach-sun7i/rf/wifi_pm.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-sunxi-new/arch/arm/mach-sun7i/rf/wifi_pm.c 2014-02-15 00:44:23.376867901 +0100 +@@ -0,0 +1,265 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "wifi_pm.h" ++ ++#define wifi_pm_msg(...) do {printk("[wifi_pm]: "__VA_ARGS__);} while(0) ++ ++ ++struct wifi_pm_ops wifi_select_pm_ops; ++static char* wifi_mod[] = {" ", ++ "bcm40181", /* 1 - BCM40181(BCM4330)*/ ++ "bcm40183", /* 2 - BCM40183(BCM4330)*/ ++ "rtl8723as", /* 3 - RTL8723AS(RF-SM02B) */ ++ "rtl8189es", /* 4 - RTL8189ES(SM89E00) */ ++ "rtl8192cu", /* 5 - RTL8192CU*/ ++ "rtl8188eu", /* 6 - RTL8188EU*/ ++ "ap6210", /* 7 - AP6210*/ ++ "ap6330", /* 8 - AP6330*/ ++ "ap6181", /* 9 - AP6181*/ ++ "rtl8723au", /* 10 - RTL8723AU */ ++}; ++ ++int wifi_pm_get_mod_type(void) ++{ ++ struct wifi_pm_ops *ops = &wifi_select_pm_ops; ++ if (ops->wifi_used) ++ return ops->module_sel; ++ else { ++ wifi_pm_msg("No select wifi, please check your config !!\n"); ++ return 0; ++ } ++} ++EXPORT_SYMBOL(wifi_pm_get_mod_type); ++ ++int wifi_pm_gpio_ctrl(char* name, int level) ++{ ++ struct wifi_pm_ops *ops = &wifi_select_pm_ops; ++ if (ops->wifi_used && ops->gpio_ctrl) ++ return ops->gpio_ctrl(name, level); ++ else { ++ wifi_pm_msg("No select wifi, please check your config !!\n"); ++ return -1; ++ } ++} ++EXPORT_SYMBOL(wifi_pm_gpio_ctrl); ++ ++void wifi_pm_power(int on) ++{ ++ struct wifi_pm_ops *ops = &wifi_select_pm_ops; ++ int power = on; ++ ++ if (ops->wifi_used && ops->power) ++ return ops->power(1, &power); ++ else { ++ wifi_pm_msg("No select wifi, please check your config !!\n"); ++ return; ++ } ++} ++EXPORT_SYMBOL(wifi_pm_power); ++ ++#ifdef CONFIG_PROC_FS ++static int wifi_pm_power_stat(char *page, char **start, off_t off, int count, int *eof, void *data) ++{ ++ struct wifi_pm_ops *ops = (struct wifi_pm_ops *)data; ++ char *p = page; ++ int power = 0; ++ ++ if (ops->power) ++ ops->power(0, &power); ++ ++ p += sprintf(p, "%s : power state %s\n", ops->mod_name, power ? "on" : "off"); ++ return p - page; ++} ++ ++static int wifi_pm_power_ctrl(struct file *file, const char __user *buffer, unsigned long count, void *data) ++{ ++ struct wifi_pm_ops *ops = (struct wifi_pm_ops *)data; ++ int power = simple_strtoul(buffer, NULL, 10); ++ ++ power = power ? 1 : 0; ++ if (ops->power) ++ ops->power(1, &power); ++ else ++ wifi_pm_msg("No power control for %s\n", ops->mod_name); ++ return sizeof(power); ++} ++ ++static inline void awwifi_procfs_attach(void) ++{ ++ char proc_rootname[] = "driver/wifi-pm"; ++ struct wifi_pm_ops *ops = &wifi_select_pm_ops; ++ ++ ops->proc_root = proc_mkdir(proc_rootname, NULL); ++ if (IS_ERR(ops->proc_root)) ++ { ++ wifi_pm_msg("failed to create procfs \"driver/wifi-pm\".\n"); ++ } ++ ++ ops->proc_power = create_proc_entry("power", 0644, ops->proc_root); ++ if (IS_ERR(ops->proc_power)) ++ { ++ wifi_pm_msg("failed to create procfs \"power\".\n"); ++ } ++ ops->proc_power->data = ops; ++ ops->proc_power->read_proc = wifi_pm_power_stat; ++ ops->proc_power->write_proc = wifi_pm_power_ctrl; ++} ++ ++static inline void awwifi_procfs_remove(void) ++{ ++ struct wifi_pm_ops *ops = &wifi_select_pm_ops; ++ char proc_rootname[] = "driver/wifi-pm"; ++ ++ remove_proc_entry("power", ops->proc_root); ++ remove_proc_entry(proc_rootname, NULL); ++} ++#else ++static inline void awwifi_procfs_attach(void) {} ++static inline void awwifi_procfs_remove(void) {} ++#endif ++ ++static int wifi_pm_get_res(void) ++{ ++ struct wifi_pm_ops *ops = &wifi_select_pm_ops; ++ ++ if (SCRIPT_PARSER_OK != script_parser_fetch(wifi_para, "wifi_used", &ops->wifi_used, 1)) { ++ pr_warning("pm: parse wifi_used failed\n"); ++ return -1; ++ } ++ if (!ops->wifi_used) { ++ pr_info("pm: wifi pm is disable in config\n"); ++ return -1; ++ } ++ ++ if (SCRIPT_PARSER_OK != script_parser_fetch(wifi_para, "wifi_sdc_id", &ops->sdio_id, 1)) { ++ pr_warning("pm: parse wifi_sdc_id failed\n"); ++ return -1; ++ } ++ ++ if (SCRIPT_PARSER_OK != script_parser_fetch(wifi_para, "wifi_usbc_id", &ops->usb_id, 1)) { ++ pr_warning("pm: parse wifi_sdc_id failed\n"); ++ return -1; ++ } ++ ++ if (SCRIPT_PARSER_OK != script_parser_fetch(wifi_para, "wifi_mod_sel", &ops->module_sel, 1)) { ++ pr_warning("pm: parse wifi_sdc_id failed\n"); ++ return -1; ++ } ++ ++ ops->mod_name = wifi_mod[ops->module_sel]; ++ ++ printk("pm: select wifi: %s\n", wifi_mod[ops->module_sel]); ++ ++ return 0; ++} ++ ++static int __devinit wifi_pm_probe(struct platform_device *pdev) ++{ ++ struct wifi_pm_ops *ops = &wifi_select_pm_ops; ++ ++ switch (ops->module_sel) { ++ case 1: /* BCM40181 */ ++ case 2: /* BCM40183 */ ++ case 3: /* RTL8723AS */ ++ case 4: /* RTL8189ES */ ++ case 5: /* RTL8192CU */ ++ case 6: /* RTL8188EU */ ++ pr_warning("wifi_pm: Unsupported wifi type!\n"); ++ break; ++ case 7: /* AP6210 */ ++ case 8: /* AP6330 */ ++ case 9: /* AP6181 */ ++ ap6xxx_gpio_init(); ++ break; ++ case 10: /* RTL8723AU */ ++ pr_warning("wifi_pm: Unsupported wifi type!\n"); ++ break; ++ default: ++ pr_warning("wifi_pm: Unsupported wifi type!\n"); ++ } ++ ++ awwifi_procfs_attach(); ++ wifi_pm_msg("wifi gpio init is OK !!\n"); ++ return 0; ++} ++ ++static int __devexit wifi_pm_remove(struct platform_device *pdev) ++{ ++ awwifi_procfs_remove(); ++ wifi_pm_msg("wifi gpio is released !!\n"); ++ return 0; ++} ++ ++#ifdef CONFIG_PM ++static int wifi_pm_suspend(struct device *dev) ++{ ++ struct wifi_pm_ops *ops = &wifi_select_pm_ops; ++ ++ if (ops->standby) ++ ops->standby(1); ++ return 0; ++} ++ ++static int wifi_pm_resume(struct device *dev) ++{ ++ struct wifi_pm_ops *ops = &wifi_select_pm_ops; ++ ++ if (ops->standby) ++ ops->standby(0); ++ return 0; ++} ++ ++static struct dev_pm_ops wifi_dev_pm_ops = { ++ .suspend = wifi_pm_suspend, ++ .resume = wifi_pm_resume, ++}; ++#endif ++ ++static struct platform_device wifi_pm_dev = { ++ .name = "wifi_pm", ++}; ++ ++static struct platform_driver wifi_pm_driver = { ++ .driver.name = "wifi_pm", ++ .driver.owner = THIS_MODULE, ++#ifdef CONFIG_PM ++ .driver.pm = &wifi_dev_pm_ops, ++#endif ++ .probe = wifi_pm_probe, ++ .remove = __devexit_p(wifi_pm_remove), ++}; ++ ++static int __init wifi_pm_init(void) ++{ ++ struct wifi_pm_ops *ops = &wifi_select_pm_ops; ++ ++ memset(ops, 0, sizeof(struct wifi_pm_ops)); ++ wifi_pm_get_res(); ++ if (!ops->wifi_used) ++ return 0; ++ ++ platform_device_register(&wifi_pm_dev); ++ return platform_driver_register(&wifi_pm_driver); ++} ++ ++static void __exit wifi_pm_exit(void) ++{ ++ struct wifi_pm_ops *ops = &wifi_select_pm_ops; ++ if (!ops->wifi_used) ++ return; ++ ++ platform_driver_unregister(&wifi_pm_driver); ++ memset(ops, 0, sizeof(struct wifi_pm_ops)); ++} ++ ++module_init(wifi_pm_init); ++module_exit(wifi_pm_exit); ++ ++MODULE_LICENSE("GPL"); ++ ++ +diff -rupN linux-sunxi/arch/arm/mach-sun7i/rf/wifi_pm.h linux-sunxi-new/arch/arm/mach-sun7i/rf/wifi_pm.h +--- linux-sunxi/arch/arm/mach-sun7i/rf/wifi_pm.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-sunxi-new/arch/arm/mach-sun7i/rf/wifi_pm.h 2014-02-15 00:44:23.376867901 +0100 +@@ -0,0 +1,30 @@ ++#ifndef WIFI__PM__H ++#define WIFI__PM__H ++ ++#include ++#define SDIO_WIFI_POWERUP (1) ++#define SDIO_WIFI_INSUSPEND (2) ++static char* wifi_para = "wifi_para"; ++ ++struct wifi_pm_ops { ++ char* mod_name; ++ int wifi_used; ++ int sdio_id; ++ int usb_id; ++ int module_sel; ++ int (*gpio_ctrl)(char* name, int level); ++ void (*standby)(int in); ++ void (*power)(int mode, int *updown); ++ ++#ifdef CONFIG_PROC_FS ++ struct proc_dir_entry *proc_root; ++ struct proc_dir_entry *proc_power; ++#endif ++}; ++ ++void ap6xxx_gpio_init(void); ++ ++extern struct wifi_pm_ops wifi_select_pm_ops; ++extern void sw_mci_rescan_card(unsigned id, unsigned insert); ++ ++#endif +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/aiutils.c linux-sunxi-new/drivers/net/wireless/bcmdhd/aiutils.c +--- linux-sunxi/drivers/net/wireless/bcmdhd/aiutils.c 2014-01-27 01:30:30.108433411 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/aiutils.c 2014-02-15 00:43:44.795014136 +0100 +@@ -2,7 +2,7 @@ + * Misc utility routines for accessing chip-specific features + * of the SiliconBackplane-based Broadcom chips. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -22,7 +22,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: aiutils.c 385510 2013-02-15 21:02:07Z $ ++ * $Id: aiutils.c 347614 2012-07-27 10:24:51Z $ + */ + #include + #include +@@ -38,7 +38,6 @@ + + #define BCM47162_DMP() (0) + #define BCM5357_DMP() (0) +-#define BCM4707_DMP() (0) + #define remap_coreid(sih, coreid) (coreid) + #define remap_corerev(sih, corerev) (corerev) + +@@ -208,7 +207,7 @@ ai_scan(si_t *sih, void *regs, uint devi + sii->oob_router = addrl; + } + } +- if (cid != GMAC_COMMON_4706_CORE_ID && cid != NS_CCB_CORE_ID) ++ if (cid != GMAC_COMMON_4706_CORE_ID) + continue; + } + +@@ -250,10 +249,10 @@ ai_scan(si_t *sih, void *regs, uint devi + "0x%x\n", addrh, sizeh, sizel)); + SI_ERROR(("First Slave ASD for" + "core 0x%04x malformed " +- "(0x%08x)\n", cid, asd)); +- goto error; +- } ++ "(0x%08x)\n", cid, asd)); ++ goto error; + } ++ } + } while (1); + } + sii->coresba[idx] = addrl; +@@ -366,7 +365,7 @@ ai_setcoreidx(si_t *sih, uint coreidx) + ASSERT(GOODREGS(sii->regs[coreidx])); + } + sii->curmap = regs = sii->regs[coreidx]; +- if (!sii->wrappers[coreidx] && (wrap != 0)) { ++ if (!sii->wrappers[coreidx]) { + sii->wrappers[coreidx] = REG_MAP(wrap, SI_CORE_SIZE); + ASSERT(GOODREGS(sii->wrappers[coreidx])); + } +@@ -542,41 +541,11 @@ ai_flag(si_t *sih) + SI_ERROR(("%s: Attempting to read USB20H DMP registers on 5357b0\n", __FUNCTION__)); + return sii->curidx; + } +- if (BCM4707_DMP()) { +- SI_ERROR(("%s: Attempting to read CHIPCOMMONB DMP registers on 4707\n", +- __FUNCTION__)); +- return sii->curidx; +- } + ai = sii->curwrap; + + return (R_REG(sii->osh, &ai->oobselouta30) & 0x1f); + } + +-uint +-ai_flag_alt(si_t *sih) +-{ +- si_info_t *sii; +- aidmp_t *ai; +- +- sii = SI_INFO(sih); +- if (BCM47162_DMP()) { +- SI_ERROR(("%s: Attempting to read MIPS DMP registers on 47162a0", __FUNCTION__)); +- return sii->curidx; +- } +- if (BCM5357_DMP()) { +- SI_ERROR(("%s: Attempting to read USB20H DMP registers on 5357b0\n", __FUNCTION__)); +- return sii->curidx; +- } +- if (BCM4707_DMP()) { +- SI_ERROR(("%s: Attempting to read CHIPCOMMONB DMP registers on 4707\n", +- __FUNCTION__)); +- return sii->curidx; +- } +- ai = sii->curwrap; +- +- return ((R_REG(sii->osh, &ai->oobselouta30) >> AI_OOBSEL_1_SHIFT) & AI_OOBSEL_MASK); +-} +- + void + ai_setint(si_t *sih, int siflag) + { +@@ -755,15 +724,15 @@ ai_core_disable(si_t *sih, uint32 bits) + /* this is in big hammer path, so don't call wl_reinit in this case... */ + } + +- W_REG(sii->osh, &ai->resetctrl, AIRC_RESET); +- dummy = R_REG(sii->osh, &ai->resetctrl); +- BCM_REFERENCE(dummy); +- OSL_DELAY(1); +- + W_REG(sii->osh, &ai->ioctrl, bits); + dummy = R_REG(sii->osh, &ai->ioctrl); + BCM_REFERENCE(dummy); + OSL_DELAY(10); ++ ++ W_REG(sii->osh, &ai->resetctrl, AIRC_RESET); ++ dummy = R_REG(sii->osh, &ai->resetctrl); ++ BCM_REFERENCE(dummy); ++ OSL_DELAY(1); + } + + /* reset and re-enable a core +@@ -824,11 +793,6 @@ ai_core_cflags_wo(si_t *sih, uint32 mask + __FUNCTION__)); + return; + } +- if (BCM4707_DMP()) { +- SI_ERROR(("%s: Accessing CHIPCOMMONB DMP register (ioctrl) on 4707\n", +- __FUNCTION__)); +- return; +- } + + ASSERT(GOODREGS(sii->curwrap)); + ai = sii->curwrap; +@@ -859,11 +823,6 @@ ai_core_cflags(si_t *sih, uint32 mask, u + __FUNCTION__)); + return 0; + } +- if (BCM4707_DMP()) { +- SI_ERROR(("%s: Accessing CHIPCOMMONB DMP register (ioctrl) on 4707\n", +- __FUNCTION__)); +- return 0; +- } + + ASSERT(GOODREGS(sii->curwrap)); + ai = sii->curwrap; +@@ -896,11 +855,6 @@ ai_core_sflags(si_t *sih, uint32 mask, u + __FUNCTION__)); + return 0; + } +- if (BCM4707_DMP()) { +- SI_ERROR(("%s: Accessing CHIPCOMMONB DMP register (ioctrl) on 4707\n", +- __FUNCTION__)); +- return 0; +- } + + ASSERT(GOODREGS(sii->curwrap)); + ai = sii->curwrap; +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/bcmevent.c linux-sunxi-new/drivers/net/wireless/bcmdhd/bcmevent.c +--- linux-sunxi/drivers/net/wireless/bcmdhd/bcmevent.c 2014-01-27 01:30:30.100433249 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/bcmevent.c 2014-02-15 00:43:44.791014047 +0100 +@@ -1,7 +1,7 @@ + /* + * bcmevent read-only data shared by kernel or app layers + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -20,7 +20,7 @@ + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. +- * $Id: bcmevent.c 389384 2013-03-06 12:20:17Z $ ++ * $Id: bcmevent.c 370587 2012-11-22 09:32:38Z $ + */ + + #include +@@ -29,7 +29,7 @@ + #include + #include + +-#if WLC_E_LAST != 125 ++#if WLC_E_LAST != 107 + #error "You need to add an entry to bcmevent_names[] for the new event" + #endif + +@@ -83,6 +83,9 @@ const bcmevent_name_t bcmevent_names[] = + { WLC_E_UNICAST_DECODE_ERROR, "UNICAST_DECODE_ERROR" }, + { WLC_E_MULTICAST_DECODE_ERROR, "MULTICAST_DECODE_ERROR" }, + { WLC_E_TRACE, "TRACE" }, ++#ifdef WLBTAMP ++ { WLC_E_BTA_HCI_EVENT, "BTA_HCI_EVENT" }, ++#endif + { WLC_E_IF, "IF" }, + #ifdef WLP2P + { WLC_E_P2P_DISC_LISTEN_COMPLETE, "WLC_E_P2P_DISC_LISTEN_COMPLETE" }, +@@ -95,7 +98,11 @@ const bcmevent_name_t bcmevent_names[] = + { WLC_E_ACTION_FRAME_RX, "ACTION_FRAME_RX" }, + { WLC_E_ACTION_FRAME_COMPLETE, "ACTION_FRAME_COMPLETE" }, + #endif +-#if 0 && (0>= 0x0620) ++#ifdef BCMWAPI_WAI ++ { WLC_E_WAI_STA_EVENT, "WAI_STA_EVENT" }, ++ { WLC_E_WAI_MSG, "WAI_MSG" }, ++#endif /* BCMWAPI_WAI */ ++#if 0 && (NDISVER >= 0x0620) + { WLC_E_PRE_ASSOC_IND, "ASSOC_RECV" }, + { WLC_E_PRE_REASSOC_IND, "REASSOC_RECV" }, + { WLC_E_CHANNEL_ADOPTED, "CHANNEL_ADOPTED" }, +@@ -106,7 +113,6 @@ const bcmevent_name_t bcmevent_names[] = + { WLC_E_REASSOC_IND_NDIS, "REASSOC_IND_NDIS"}, + { WLC_E_ACTION_FRAME_RX_NDIS, "WLC_E_ACTION_FRAME_RX_NDIS" }, + { WLC_E_AUTH_REQ, "WLC_E_AUTH_REQ" }, +- { WLC_E_IBSS_COALESCE, "IBSS COALESCE" }, + #endif + { WLC_E_ESCAN_RESULT, "WLC_E_ESCAN_RESULT" }, + { WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE, "WLC_E_AF_OFF_CHAN_COMPLETE" }, +@@ -137,22 +143,9 @@ const bcmevent_name_t bcmevent_names[] = + #ifdef WLTDLS + { WLC_E_TDLS_PEER_EVENT, "TDLS_PEER_EVENT" }, + #endif /* WLTDLS */ +- { WLC_E_NATIVE, "NATIVE" }, +-#ifdef WLPKTDLYSTAT +- { WLC_E_PKTDELAY_IND, "PKTDELAY_IND" }, +-#endif /* WLPKTDLYSTAT */ + { WLC_E_SERVICE_FOUND, "SERVICE_FOUND" }, +- { WLC_E_GAS_FRAGMENT_RX, "GAS_FRAGMENT_RX" }, +- { WLC_E_GAS_COMPLETE, "GAS_COMPLETE" }, + { WLC_E_P2PO_ADD_DEVICE, "P2PO_DEV_FOUND" }, + { WLC_E_P2PO_DEL_DEVICE, "P2PO_DEV_LOST" }, +-#ifdef WLWNM +- { WLC_E_WNM_STA_SLEEP, "WMM_STA_SLEEP" }, +-#endif /* WLWNM */ +-#if defined(WL_PROXDETECT) +- { WLC_E_PROXD, "WLC_E_PROXD" }, +-#endif +- { WLC_E_CCA_CHAN_QUAL, "CCA_BASED_CHANNEL_QUALITY" }, + }; + + const int bcmevent_names_size = ARRAYSIZE(bcmevent_names); +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/bcmsdh.c linux-sunxi-new/drivers/net/wireless/bcmdhd/bcmsdh.c +--- linux-sunxi/drivers/net/wireless/bcmdhd/bcmsdh.c 2014-01-27 01:30:30.108433411 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/bcmsdh.c 2014-02-15 00:43:44.795014136 +0100 +@@ -2,7 +2,7 @@ + * BCMSDH interface glue + * implement bcmsdh API for SDIOH driver + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -22,7 +22,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: bcmsdh.c 373331 2012-12-07 04:46:22Z $ ++ * $Id: bcmsdh.c 373330 2012-12-07 04:46:17Z $ + */ + + /** +@@ -74,6 +74,26 @@ bcmsdh_enable_hw_oob_intr(bcmsdh_info_t + } + #endif + ++#if defined(HW_OOB) ++#include ++void ++bcmsdh_config_hw_oob_intr(bcmsdh_info_t *sdh, uint chip) ++{ ++ uint32 gpiocontrol, addr; ++ ++ printf("%s: Enter\n", __FUNCTION__); ++ if (CHIPID(chip) == BCM43362_CHIP_ID) { ++ addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, gpiocontrol); ++ gpiocontrol = bcmsdh_reg_read(sdh, addr, 4); ++ gpiocontrol |= 0x2; ++ bcmsdh_reg_write(sdh, addr, 4, gpiocontrol); ++ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, 0x10005, 0xf, NULL); ++ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, 0x10006, 0x0, NULL); ++ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, 0x10007, 0x2, NULL); ++ } ++} ++#endif ++ + /* Attach BCMSDH layer to SDIO Host Controller Driver + * + * @param osh OSL Handle. +@@ -728,10 +748,10 @@ bcmsdh_gpioout(void *sdh, uint32 gpio, b + + #ifdef BCMSDIOH_TXGLOM + void +-bcmsdh_glom_post(void *sdh, uint8 *frame, void *pkt, uint len) ++bcmsdh_glom_post(void *sdh, uint8 *frame, uint len) + { + bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; +- sdioh_glom_post(bcmsdh->sdioh, frame, pkt, len); ++ sdioh_glom_post(bcmsdh->sdioh, frame, len); + } + + void +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/bcmsdh_linux.c linux-sunxi-new/drivers/net/wireless/bcmdhd/bcmsdh_linux.c +--- linux-sunxi/drivers/net/wireless/bcmdhd/bcmsdh_linux.c 2014-01-27 01:30:30.108433411 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/bcmsdh_linux.c 2014-02-15 00:43:44.795014136 +0100 +@@ -1,7 +1,7 @@ + /* + * SDIO access interface for drivers - linux specific (pci only) + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -21,7 +21,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: bcmsdh_linux.c 414953 2013-07-26 17:36:27Z $ ++ * $Id: bcmsdh_linux.c 373359 2012-12-07 06:36:37Z $ + */ + + /** +@@ -40,6 +40,8 @@ + #include + #include + #include ++#include ++#include + + #if defined(OOB_INTR_ONLY) + #include +@@ -47,8 +49,11 @@ extern void dhdsdio_isr(void * args); + #include + #include + #include ++#include ++#include + #endif + ++ + /** + * SDIO Host Controller info + */ +@@ -75,13 +80,11 @@ struct bcmsdh_hc { + }; + static bcmsdh_hc_t *sdhcinfo = NULL; + +-struct device *pm_dev; +- + /* driver info, initialized when bcmsdh_register is called */ + static bcmsdh_driver_t drvinfo = {NULL, NULL}; + + /* debugging macros */ +-#define SDLX_MSG(x) ++#define SDLX_MSG(x) printf x + + /** + * Checks to see if vendor and device IDs match a supported SDIO Host Controller. +@@ -154,7 +157,7 @@ static + int bcmsdh_probe(struct device *dev) + { + osl_t *osh = NULL; +- bcmsdh_hc_t *sdhc = NULL, *sdhc_org = sdhcinfo; ++ bcmsdh_hc_t *sdhc = NULL; + ulong regs = 0; + bcmsdh_info_t *sdh = NULL; + #if !defined(BCMLXSDMMC) && defined(BCMPLATFORM_BUS) +@@ -169,7 +172,7 @@ int bcmsdh_probe(struct device *dev) + pdev = to_platform_device(dev); + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + irq = platform_get_irq(pdev, 0); +- if (!r || irq < 0) ++ if (!r || irq == NO_IRQ) + return -ENXIO; + #endif + +@@ -183,9 +186,13 @@ int bcmsdh_probe(struct device *dev) + + /* Get customer specific OOB IRQ parametres: IRQ number as IRQ type */ + irq = dhd_customer_oob_irq_map(&irq_flags); ++#if defined(CONFIG_ARCH_RHEA) || defined(CONFIG_ARCH_CAPRI) ++ /* Do not disable this IRQ during suspend */ ++ irq_flags |= IRQF_NO_SUSPEND; ++#endif /* defined(CONFIG_ARCH_RHEA) || defined(CONFIG_ARCH_CAPRI) */ + if (irq < 0) { + SDLX_MSG(("%s: Host irq is not defined\n", __FUNCTION__)); +- goto err; ++ return 1; + } + #endif + /* allocate SDIO Host Controller state info */ +@@ -230,11 +237,6 @@ int bcmsdh_probe(struct device *dev) + sdhc->next = sdhcinfo; + sdhcinfo = sdhc; + +-#if !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) +- if (!device_init_wakeup(dev, 1)) +- pm_dev = dev; +-#endif /* !CONFIG_HAS_WAKELOCK */ +- + /* Read the vendor/device ID from the CIS */ + vendevid = bcmsdh_query_device(sdh); + /* try to attach to the target device */ +@@ -253,7 +255,6 @@ err: + if (sdhc->sdh) + bcmsdh_detach(sdhc->osh, sdhc->sdh); + MFREE(osh, sdhc, sizeof(bcmsdh_hc_t)); +- sdhcinfo = sdhc_org; + } + if (osh) + osl_detach(osh); +@@ -267,20 +268,18 @@ int bcmsdh_remove(struct device *dev) + { + bcmsdh_hc_t *sdhc, *prev; + osl_t *osh; +- int sdhcinfo_null = false; ++ ++ sdhc = sdhcinfo; ++ drvinfo.detach(sdhc->ch); ++ bcmsdh_detach(sdhc->osh, 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 { +- if (sdhc->next != NULL) { +- SDLX_MSG(("%s: more SDHC exist, should be care about it\n", +- __FUNCTION__)); +- } +- sdhcinfo_null = true; +- } ++ else ++ sdhcinfo = NULL; + break; + } + prev = sdhc; +@@ -290,20 +289,6 @@ int bcmsdh_remove(struct device *dev) + return 0; + } + +- /* detach ch & sdhc if dev is valid */ +- drvinfo.detach(sdhc->ch); +- bcmsdh_detach(sdhc->osh, sdhc->sdh); +- +-#if !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) +- if (pm_dev) { +- device_init_wakeup(pm_dev, 0); +- pm_dev = NULL; +- } +-#endif /* !CONFIG_HAS_WAKELOCK */ +- +- if (sdhcinfo_null == true) +- sdhcinfo = NULL; +- + /* release SDIO Host Controller info */ + osh = sdhc->osh; + MFREE(osh, sdhc, sizeof(bcmsdh_hc_t)); +@@ -428,10 +413,6 @@ bcmsdh_pci_probe(struct pci_dev *pdev, c + /* match this pci device with what we support */ + /* we can't solely rely on this to believe it is our SDIO Host Controller! */ + if (!bcmsdh_chipmatch(pdev->vendor, pdev->device)) { +- if (pdev->vendor == VENDOR_BROADCOM) { +- SDLX_MSG(("%s: Unknown Broadcom device (vendor: %#x, device: %#x).\n", +- __FUNCTION__, pdev->vendor, pdev->device)); +- } + return -ENODEV; + } + +@@ -601,7 +582,18 @@ bcmsdh_unregister(void) + #endif /* BCMPLATFORM_BUS */ + } + ++int bcmsdh_set_drvdata(void * dhdp) ++{ ++ SDLX_MSG(("%s Enter \n", __FUNCTION__)); ++ ++ dev_set_drvdata(sdhcinfo->dev, dhdp); ++ ++ return 0; ++} ++ + #if defined(OOB_INTR_ONLY) ++#define CONFIG_ARCH_SUN6I_BCMDHD 1 ++ + void bcmsdh_oob_intr_set(bool enable) + { + static bool curstate = 1; +@@ -609,12 +601,15 @@ void bcmsdh_oob_intr_set(bool enable) + + spin_lock_irqsave(&sdhcinfo->irq_lock, flags); + if (curstate != enable) { +- if (enable) +- enable_irq(sdhcinfo->oob_irq); +- else +- disable_irq_nosync(sdhcinfo->oob_irq); ++ if(enable) { ++ enable_irq(sdhcinfo->oob_irq); ++ } ++ else { ++ disable_irq_nosync(sdhcinfo->oob_irq); ++ } + curstate = enable; + } ++ + spin_unlock_irqrestore(&sdhcinfo->irq_lock, flags); + } + +@@ -636,26 +631,39 @@ static irqreturn_t wlan_oob_irq(int irq, + return IRQ_HANDLED; + } + ++extern int wl_host_wake_irqno; ++irqreturn_t bcmdhd_gpio_irq_handler(int irq, void *dev) ++{ ++ wlan_oob_irq(0, NULL); ++ return IRQ_HANDLED; ++} ++ + int bcmsdh_register_oob_intr(void * dhdp) + { + int error = 0; +- ++ int ret; + SDLX_MSG(("%s Enter \n", __FUNCTION__)); + + /* 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", __FUNCTION__, + (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; + ++ ret = request_irq(wl_host_wake_irqno, bcmdhd_gpio_irq_handler, IRQF_DISABLED| IRQF_SHARED| IRQF_TRIGGER_HIGH, "bcmdhd_gpio_irq", (void *)&wl_host_wake_irqno); ++ if (ret) { ++ pr_err("bcmdhd: request irq%d failed\n", wl_host_wake_irqno); ++ return -1; ++ } ++ ++#if defined(CONFIG_ARCH_RHEA) || defined(CONFIG_ARCH_CAPRI) || defined(CONFIG_ARCH_SUN6I_BCMDHD) ++ if (device_may_wakeup(sdhcinfo->dev)) { ++#endif + error = enable_irq_wake(sdhcinfo->oob_irq); ++#if defined(CONFIG_ARCH_RHEA) || defined(CONFIG_ARCH_CAPRI) || defined(CONFIG_ARCH_SUN6I_BCMDHD) ++ } ++#endif + if (error) + SDLX_MSG(("%s enable_irq_wake error=%d \n", __FUNCTION__, error)); + sdhcinfo->oob_irq_registered = TRUE; +@@ -668,13 +676,22 @@ int bcmsdh_register_oob_intr(void * dhdp + void bcmsdh_set_irq(int flag) + { + if (sdhcinfo->oob_irq_registered && sdhcinfo->oob_irq_enable_flag != flag) { +- SDLX_MSG(("%s Flag = %d", __FUNCTION__, flag)); ++ SDLX_MSG(("%s Flag = %d\n", __FUNCTION__, flag)); + sdhcinfo->oob_irq_enable_flag = flag; + if (flag) { + enable_irq(sdhcinfo->oob_irq); ++ ++#if defined(CONFIG_ARCH_RHEA) || defined(CONFIG_ARCH_CAPRI) || defined(CONFIG_ARCH_SUN6I_BCMDHD) ++ if (device_may_wakeup(sdhcinfo->dev)) ++#endif + enable_irq_wake(sdhcinfo->oob_irq); + } else { ++#if defined(CONFIG_ARCH_RHEA) || defined(CONFIG_ARCH_CAPRI) || defined(CONFIG_ARCH_SUN6I_BCMDHD) ++ if (device_may_wakeup(sdhcinfo->dev)) ++#endif + disable_irq_wake(sdhcinfo->oob_irq); ++ ++ + disable_irq(sdhcinfo->oob_irq); + } + } +@@ -685,19 +702,15 @@ void bcmsdh_unregister_oob_intr(void) + SDLX_MSG(("%s: Enter\n", __FUNCTION__)); + + if (sdhcinfo->oob_irq_registered == TRUE) { +- bcmsdh_set_irq(FALSE); +- free_irq(sdhcinfo->oob_irq, NULL); ++ ++ if(0 != wl_host_wake_irqno) { ++ pr_info("bcmdhd: free_irq %d\n", wl_host_wake_irqno); ++ free_irq(wl_host_wake_irqno, &wl_host_wake_irqno); ++ } ++ + sdhcinfo->oob_irq_registered = FALSE; + } + } +- +-bool bcmsdh_is_oob_intr_registered(void) +-{ +- if (sdhcinfo) +- return sdhcinfo->oob_irq_registered; +- else +- return FALSE; +-} + #endif + + #if defined(BCMLXSDMMC) +@@ -735,10 +748,6 @@ module_param(sd_f2_blocksize, int, 0); + #ifdef BCMSDIOH_STD + extern int sd_uhsimode; + module_param(sd_uhsimode, int, 0); +-extern uint sd_tuning_period; +-module_param(sd_tuning_period, uint, 0); +-extern int sd_delay_value; +-module_param(sd_delay_value, uint, 0); + #endif + + #ifdef BCMSDIOH_TXGLOM +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c linux-sunxi-new/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c +--- linux-sunxi/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c 2014-01-27 01:30:30.108433411 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c 2014-02-15 00:43:44.795014136 +0100 +@@ -1,7 +1,7 @@ + /* + * BCMSDH Function Driver for the native SDIO/MMC driver in the Linux Kernel + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -21,7 +21,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: bcmsdh_sdmmc.c 418714 2013-08-16 13:21:09Z $ ++ * $Id: bcmsdh_sdmmc.c 362913 2012-10-15 11:26:11Z $ + */ + #include + +@@ -59,6 +59,7 @@ static void IRQHandlerF2(struct sdio_fun + #endif /* !defined(OOB_INTR_ONLY) */ + static int sdioh_sdmmc_get_cisaddr(sdioh_info_t *sd, uint32 regaddr); + extern int sdio_reset_comm(struct mmc_card *card); ++extern int sw_mci_check_r1_ready(struct mmc_host* mmc, unsigned ms); + + extern PBCMSDH_SDMMC_INSTANCE gInstance; + +@@ -76,18 +77,6 @@ uint sd_clock = 1; /* Default to SD Clo + uint sd_hiok = FALSE; /* Don't use hi-speed mode by default */ + uint sd_msglevel = 0x01; + uint sd_use_dma = TRUE; +- +-#ifdef BCMSDIOH_TXGLOM +-#ifndef CUSTOM_TXGLOM +-#define CUSTOM_TXGLOM 0 +-#endif +-uint sd_txglom = CUSTOM_TXGLOM; +-#endif /* BCMSDIOH_TXGLOM */ +- +-#ifndef CUSTOM_RXCHAIN +-#define CUSTOM_RXCHAIN 0 +-#endif +- + 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); +@@ -166,7 +155,7 @@ sdioh_attach(osl_t *osh, void *bar0, uin + sd->sd_blockmode = TRUE; + sd->use_client_ints = TRUE; + sd->client_block_size[0] = 64; +- sd->use_rxchain = CUSTOM_RXCHAIN; ++ sd->use_rxchain = FALSE; + + gInstance->sd = sd; + +@@ -176,14 +165,12 @@ sdioh_attach(osl_t *osh, void *bar0, uin + + sd->client_block_size[1] = 64; + err_ret = sdio_set_block_size(gInstance->func[1], 64); +- /* Release host controller F1 */ +- sdio_release_host(gInstance->func[1]); + if (err_ret) { + sd_err(("bcmsdh_sdmmc: Failed to set F1 blocksize\n")); +- MFREE(sd->osh, sd, sizeof(sdioh_info_t)); +- return NULL; + } + ++ /* Release host controller F1 */ ++ sdio_release_host(gInstance->func[1]); + } else { + sd_err(("%s:gInstance->func[1] is null\n", __FUNCTION__)); + MFREE(sd->osh, sd, sizeof(sdioh_info_t)); +@@ -196,15 +183,13 @@ sdioh_attach(osl_t *osh, void *bar0, uin + + sd->client_block_size[2] = sd_f2_blocksize; + err_ret = sdio_set_block_size(gInstance->func[2], sd_f2_blocksize); +- /* Release host controller F2 */ +- sdio_release_host(gInstance->func[2]); + if (err_ret) { + sd_err(("bcmsdh_sdmmc: Failed to set F2 blocksize to %d\n", + sd_f2_blocksize)); +- MFREE(sd->osh, sd, sizeof(sdioh_info_t)); +- return NULL; + } + ++ /* Release host controller F2 */ ++ sdio_release_host(gInstance->func[2]); + } else { + sd_err(("%s:gInstance->func[2] is null\n", __FUNCTION__)); + MFREE(sd->osh, sd, sizeof(sdioh_info_t)); +@@ -266,9 +251,9 @@ sdioh_enable_func_intr(void) + return SDIOH_API_RC_FAIL; + } + +- /* Enable F1 and F2 interrupts, clear master enable */ +- reg &= ~INTR_CTL_MASTER_EN; +- reg |= (INTR_CTL_FUNC1_EN | INTR_CTL_FUNC2_EN); ++ /* 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]); + +@@ -795,10 +780,11 @@ sdioh_cis_read(sdioh_info_t *sd, uint fu + extern SDIOH_API_RC + sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *byte) + { +- int err_ret = 0; ++ int err_ret; + #if defined(MMC_SDIO_ABORT) + int sdio_abort_retry = MMC_SDIO_ABORT_RETRY_LIMIT; + #endif ++ int ret = 0; + + sd_info(("%s: rw=%d, func=%d, addr=0x%05x\n", __FUNCTION__, rw, func, regaddr)); + +@@ -833,14 +819,18 @@ sdioh_request_byte(sdioh_info_t *sd, uin + #if defined(MMC_SDIO_ABORT) + /* to allow abort command through F1 */ + else if (regaddr == SDIOD_CCCR_IOABORT) { ++ /* Because of SDIO3.0 host issue on Manta, ++ * sometimes the abort fails. ++ * Retrying again will fix this issue. ++ */ + while (sdio_abort_retry--) { + if (gInstance->func[func]) { + 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 +- */ ++ * 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]); +@@ -882,12 +872,14 @@ sdioh_request_byte(sdioh_info_t *sd, uin + } + } + ++ //AW judge sdio read write timeout, 1s ++ ret = sw_mci_check_r1_ready(gInstance->func[func]->card->host, 1000); ++ if (ret != 0) ++ printk(("%s data timeout.\n", __FUNCTION__)); ++ + if (err_ret) { +- if ((regaddr == 0x1001F) && (err_ret == -110)) { +- } else { +- sd_err(("bcmsdh_sdmmc: Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n", +- rw ? "Write" : "Read", func, regaddr, *byte, 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); +@@ -901,6 +893,7 @@ sdioh_request_word(sdioh_info_t *sd, uin + #if defined(MMC_SDIO_ABORT) + int sdio_abort_retry = MMC_SDIO_ABORT_RETRY_LIMIT; + #endif ++ int ret = 0; + + if (func == 0) { + sd_err(("%s: Only CMD52 allowed to F0.\n", __FUNCTION__)); +@@ -915,7 +908,7 @@ sdioh_request_word(sdioh_info_t *sd, uin + /* Claim host controller */ + sdio_claim_host(gInstance->func[func]); + +- if(rw) { /* CMD52 Write */ ++ if(rw) { /* CMD53 Write */ + if (nbytes == 4) { + sdio_writel(gInstance->func[func], *word, addr, &err_ret); + } else if (nbytes == 2) { +@@ -933,6 +926,11 @@ sdioh_request_word(sdioh_info_t *sd, uin + } + } + ++ //AW judge sdio read write timeout, 1s ++ ret = sw_mci_check_r1_ready(gInstance->func[func]->card->host, 1000); ++ if (ret != 0) ++ printk(("%s data timeout.\n", __FUNCTION__)); ++ + /* Release host controller */ + sdio_release_host(gInstance->func[func]); + +@@ -943,10 +941,10 @@ sdioh_request_word(sdioh_info_t *sd, uin + if (gInstance->func[0]) { + sdio_claim_host(gInstance->func[0]); + /* +- * this sdio_f0_writeb() can be replaced with another api +- * depending upon MMC driver change. +- * As of this time, this is temporaray one +- */ ++ * 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[0], + func, SDIOD_CCCR_IOABORT, &err_ret); + sdio_release_host(gInstance->func[0]); +@@ -957,103 +955,14 @@ sdioh_request_word(sdioh_info_t *sd, uin + if (err_ret) + #endif /* MMC_SDIO_ABORT */ + { +- sd_err(("bcmsdh_sdmmc: Failed to %s word, Err: 0x%08x", +- rw ? "Write" : "Read", err_ret)); ++ sd_err(("bcmsdh_sdmmc: Failed to %s word, Err: 0x%08x\n", ++ rw ? "Write" : "Read", err_ret)); + } + } + + return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL); + } + +-#ifdef BCMSDIOH_TXGLOM +-void +-sdioh_glom_post(sdioh_info_t *sd, uint8 *frame, void *pkt, uint len) +-{ +- void *phead = sd->glom_info.glom_pkt_head; +- void *ptail = sd->glom_info.glom_pkt_tail; +- +- BCM_REFERENCE(frame); +- +- ASSERT(!PKTLINK(pkt)); +- if (!phead) { +- ASSERT(!phead); +- sd->glom_info.glom_pkt_head = sd->glom_info.glom_pkt_tail = pkt; +- } +- else { +- ASSERT(ptail); +- PKTSETNEXT(sd->osh, ptail, pkt); +- sd->glom_info.glom_pkt_tail = pkt; +- } +- sd->glom_info.count++; +-} +- +-void +-sdioh_glom_clear(sdioh_info_t *sd) +-{ +- void *pnow, *pnext; +- +- pnext = sd->glom_info.glom_pkt_head; +- +- if (!pnext) { +- sd_err(("sdioh_glom_clear: no first packet to clear!\n")); +- return; +- } +- +- while (pnext) { +- pnow = pnext; +- pnext = PKTNEXT(sd->osh, pnow); +- PKTSETNEXT(sd->osh, pnow, NULL); +- sd->glom_info.count--; +- } +- +- sd->glom_info.glom_pkt_head = NULL; +- sd->glom_info.glom_pkt_tail = NULL; +- if (sd->glom_info.count != 0) { +- sd_err(("sdioh_glom_clear: glom count mismatch!\n")); +- sd->glom_info.count = 0; +- } +-} +- +-uint +-sdioh_set_mode(sdioh_info_t *sd, uint mode) +-{ +- if (mode == SDPCM_TXGLOM_CPY) +- sd->txglom_mode = mode; +- else if (mode == SDPCM_TXGLOM_MDESC) +- sd->txglom_mode = mode; +- +- return (sd->txglom_mode); +-} +- +-bool +-sdioh_glom_enabled(void) +-{ +- return sd_txglom; +-} +-#endif /* BCMSDIOH_TXGLOM */ +- +-static INLINE int sdioh_request_packet_align(uint pkt_len, uint write, uint func, int blk_size) +-{ +- /* Align Patch */ +- if (!write || pkt_len < 32) +- pkt_len = (pkt_len + 3) & 0xFFFFFFFC; +- else if ((pkt_len > blk_size) && (pkt_len % blk_size)) { +- if (func == SDIO_FUNC_2) { +- sd_err(("%s: [%s] dhd_sdio must align %d bytes" +- " packet larger than a %d bytes blk size by a blk size\n", +- __FUNCTION__, write ? "W" : "R", pkt_len, blk_size)); +- } +- pkt_len += blk_size - (pkt_len % blk_size); +- } +-#ifdef CONFIG_MMC_MSM7X00A +- if ((pkt_len % 64) == 32) { +- sd_err(("%s: Rounding up TX packet +=32\n", __FUNCTION__)); +- pkt_len += 32; +- } +-#endif /* CONFIG_MMC_MSM7X00A */ +- return pkt_len; +-} +- + static SDIOH_API_RC + sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func, + uint addr, void *pkt) +@@ -1061,20 +970,14 @@ sdioh_request_packet(sdioh_info_t *sd, u + bool fifo = (fix_inc == SDIOH_DATA_FIX); + uint32 SGCount = 0; + int err_ret = 0; +- void *pnext; ++ void *pnext, *pprev; + uint ttl_len, dma_len, lft_len, xfred_len, pkt_len; + uint blk_num; + int blk_size; + struct mmc_request mmc_req; + struct mmc_command mmc_cmd; + struct mmc_data mmc_dat; +-#ifdef BCMSDIOH_TXGLOM +- uint8 *localbuf = NULL; +- uint local_plen = 0; +- bool need_txglom = write && sdioh_glom_enabled() && +- (pkt == sd->glom_info.glom_pkt_tail) && +- (sd->glom_info.glom_pkt_head != sd->glom_info.glom_pkt_tail); +-#endif /* BCMSDIOH_TXGLOM */ ++ int ret = 0; + + sd_trace(("%s: Enter\n", __FUNCTION__)); + +@@ -1083,29 +986,18 @@ sdioh_request_packet(sdioh_info_t *sd, u + DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL); + + ttl_len = xfred_len = 0; +-#ifdef BCMSDIOH_TXGLOM +- if (need_txglom) { +- pkt = sd->glom_info.glom_pkt_head; +- } +-#endif /* BCMSDIOH_TXGLOM */ +- + /* at least 4 bytes alignment of skb buff is guaranteed */ + for (pnext = pkt; pnext; pnext = PKTNEXT(sd->osh, pnext)) + ttl_len += PKTLEN(sd->osh, pnext); + + blk_size = sd->client_block_size[func]; +- if (((!write && sd->use_rxchain) || +-#ifdef BCMSDIOH_TXGLOM +- (need_txglom && sd->txglom_mode == SDPCM_TXGLOM_MDESC) || +-#endif +- 0) && (ttl_len >= blk_size)) { +- blk_num = ttl_len / blk_size; +- dma_len = blk_num * blk_size; +- } else { ++ if (!sd->use_rxchain || ttl_len <= blk_size) { + blk_num = 0; + dma_len = 0; ++ } else { ++ blk_num = ttl_len / blk_size; ++ dma_len = blk_num * blk_size; + } +- + lft_len = ttl_len - dma_len; + + sd_trace(("%s: %s %dB to func%d:%08x, %d blks with DMA, %dB leftover\n", +@@ -1118,6 +1010,7 @@ sdioh_request_packet(sdioh_info_t *sd, u + memset(&mmc_dat, 0, sizeof(struct mmc_data)); + + /* Set up DMA descriptors */ ++ pprev = pkt; + for (pnext = pkt; + pnext && dma_len; + pnext = PKTNEXT(sd->osh, pnext)) { +@@ -1171,8 +1064,12 @@ sdioh_request_packet(sdioh_info_t *sd, u + __FUNCTION__, + write ? "write" : "read", + err_ret)); +- } +- if (!fifo) { ++ sd_err(("%s:Disabling rxchain and fire it with PIO\n", ++ __FUNCTION__)); ++ sd->use_rxchain = FALSE; ++ pkt = pprev; ++ lft_len = ttl_len; ++ } else if (!fifo) { + addr = addr + ttl_len - lft_len - dma_len; + } + } +@@ -1184,79 +1081,27 @@ sdioh_request_packet(sdioh_info_t *sd, u + for (pnext = pkt; pnext; pnext = PKTNEXT(sd->osh, pnext)) { + uint8 *buf = (uint8*)PKTDATA(sd->osh, pnext) + + xfred_len; +- int pad = 0; + pkt_len = PKTLEN(sd->osh, pnext); + if (0 != xfred_len) { + pkt_len -= xfred_len; + xfred_len = 0; + } +-#ifdef BCMSDIOH_TXGLOM +- if (need_txglom) { +- if (!localbuf) { +- uint prev_lft_len = lft_len; +- lft_len = sdioh_request_packet_align(lft_len, write, +- func, blk_size); +- +- if (lft_len > prev_lft_len) { +- sd_err(("%s: padding is unexpected! lft_len %d," +- " prev_lft_len %d %s\n", +- __FUNCTION__, lft_len, prev_lft_len, +- write ? "Write" : "Read")); +- } +- +- localbuf = (uint8 *)MALLOC(sd->osh, lft_len); +- if (localbuf == NULL) { +- sd_err(("%s: %s TXGLOM: localbuf malloc FAILED\n", +- __FUNCTION__, (write) ? "TX" : "RX")); +- need_txglom = FALSE; +- goto txglomfail; +- } +- } +- bcopy(buf, (localbuf + local_plen), pkt_len); +- local_plen += pkt_len; + +- if (PKTNEXT(sd->osh, pnext)) { +- continue; +- } +- +- buf = localbuf; +- pkt_len = local_plen; +- } +- +-txglomfail: +-#endif /* BCMSDIOH_TXGLOM */ ++ /* Align Patch ++ * read or small packet(ex:BDC header) skip 32 byte align ++ * otherwise, padding DHD_SDALIGN for performance ++ */ ++ if (write == 0 || pkt_len < 32) ++ pkt_len = (pkt_len + 3) & 0xFFFFFFFC; ++ else if (pkt_len % blk_size) ++ pkt_len += blk_size - (pkt_len % blk_size); + +- if ( +-#ifdef BCMSDIOH_TXGLOM +- !need_txglom && +-#endif +- TRUE) { +- int align_pkt_len = 0; +- align_pkt_len = sdioh_request_packet_align(pkt_len, write, +- func, blk_size); +- +- pad = align_pkt_len - pkt_len; +- if (pad > 0) { +- if (func == SDIO_FUNC_2) { +- sd_err(("%s: padding is unexpected! pkt_len %d," +- " PKTLEN %d lft_len %d %s\n", +- __FUNCTION__, pkt_len, PKTLEN(sd->osh, pnext), +- lft_len, write ? "Write" : "Read")); +- } +- if (PKTTAILROOM(sd->osh, pkt) < pad) { +- sd_info(("%s: insufficient tailroom %d, pad %d," +- " lft_len %d pktlen %d, func %d %s\n", +- __FUNCTION__, (int)PKTTAILROOM(sd->osh, pkt), +- pad, lft_len, PKTLEN(sd->osh, pnext), func, +- write ? "W" : "R")); +- if (PKTPADTAILROOM(sd->osh, pkt, pad)) { +- sd_err(("%s: padding error size %d.\n", +- __FUNCTION__, pad)); +- return SDIOH_API_RC_FAIL; +- } +- } +- } ++#ifdef CONFIG_MMC_MSM7X00A ++ if ((pkt_len % 64) == 32) { ++ sd_trace(("%s: Rounding up TX packet +=32\n", __FUNCTION__)); ++ pkt_len += 32; + } ++#endif /* CONFIG_MMC_MSM7X00A */ + + if ((write) && (!fifo)) + err_ret = sdio_memcpy_toio( +@@ -1275,6 +1120,11 @@ txglomfail: + gInstance->func[func], + buf, addr, pkt_len); + ++ //AW judge sdio read write timeout, 1s ++ ret = sw_mci_check_r1_ready(gInstance->func[func]->card->host, 1000); ++ if (ret != 0) ++ printk(("%s data timeout.\n", __FUNCTION__)); ++ + if (err_ret) + sd_err(("%s: %s FAILED %p[%d], addr=0x%05x, pkt_len=%d, ERR=%d\n", + __FUNCTION__, +@@ -1292,10 +1142,6 @@ txglomfail: + } + sdio_release_host(gInstance->func[func]); + } +-#ifdef BCMSDIOH_TXGLOM +- if (localbuf) +- MFREE(sd->osh, localbuf, lft_len); +-#endif /* BCMSDIOH_TXGLOM */ + + sd_trace(("%s: Exit\n", __FUNCTION__)); + return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL); +@@ -1315,51 +1161,89 @@ txglomfail: + */ + 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, uint8 *buffer, void *pkt) ++ uint addr, uint reg_width, uint buflen_u, uint8 *buffer, void *pkt) + { + SDIOH_API_RC Status; +- void *tmppkt; +- void *orig_buf = NULL; +- uint copylen = 0; ++ void *mypkt = NULL; + + sd_trace(("%s: Enter\n", __FUNCTION__)); + + 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) { +- /* Case 1: we don't have a packet. */ +- orig_buf = buffer; +- copylen = buflen_u; +- } else if ((ulong)PKTDATA(sd->osh, pkt) & DMA_ALIGN_MASK) { +- /* Case 2: We have a packet, but it is unaligned. +- * in this case, we cannot have a chain. +- */ +- ASSERT(PKTNEXT(sd->osh, pkt) == NULL); ++ sd_data(("%s: Creating new %s Packet, len=%d\n", ++ __FUNCTION__, write ? "TX" : "RX", buflen_u)); ++#ifdef CONFIG_DHD_USE_STATIC_BUF ++ if (!(mypkt = PKTGET_STATIC(sd->osh, buflen_u, write ? TRUE : FALSE))) ++#else ++ if (!(mypkt = PKTGET(sd->osh, buflen_u, write ? TRUE : FALSE))) ++#endif /* CONFIG_DHD_USE_STATIC_BUF */ ++ { ++ sd_err(("%s: PKTGET failed: len %d\n", ++ __FUNCTION__, buflen_u)); ++ return SDIOH_API_RC_FAIL; ++ } + +- orig_buf = PKTDATA(sd->osh, pkt); +- copylen = PKTLEN(sd->osh, pkt); +- } ++ /* For a write, copy the buffer data into the packet. */ ++ if (write) { ++ bcopy(buffer, PKTDATA(sd->osh, mypkt), 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) { ++ bcopy(PKTDATA(sd->osh, mypkt), buffer, buflen_u); ++ } ++#ifdef CONFIG_DHD_USE_STATIC_BUF ++ PKTFREE_STATIC(sd->osh, mypkt, write ? TRUE : FALSE); ++#else ++ PKTFREE(sd->osh, mypkt, write ? TRUE : FALSE); ++#endif /* CONFIG_DHD_USE_STATIC_BUF */ ++ } else if (((uint32)(PKTDATA(sd->osh, pkt)) & DMA_ALIGN_MASK) != 0) { ++ /* Case 2: We have a packet, but it is unaligned. */ ++ ++ /* In this case, we cannot have a chain. */ ++ ASSERT(PKTNEXT(sd->osh, pkt) == NULL); + +- tmppkt = pkt; +- if (copylen) { +- tmppkt = PKTGET_STATIC(sd->osh, copylen, write ? TRUE : FALSE); +- if (tmppkt == NULL) { +- sd_err(("%s: PKTGET failed: len %d\n", __FUNCTION__, copylen)); ++ sd_data(("%s: Creating aligned %s Packet, len=%d\n", ++ __FUNCTION__, write ? "TX" : "RX", PKTLEN(sd->osh, pkt))); ++#ifdef CONFIG_DHD_USE_STATIC_BUF ++ if (!(mypkt = PKTGET_STATIC(sd->osh, PKTLEN(sd->osh, pkt), write ? TRUE : FALSE))) ++#else ++ if (!(mypkt = PKTGET(sd->osh, PKTLEN(sd->osh, pkt), write ? TRUE : FALSE))) ++#endif /* CONFIG_DHD_USE_STATIC_BUF */ ++ { ++ sd_err(("%s: PKTGET failed: len %d\n", ++ __FUNCTION__, PKTLEN(sd->osh, pkt))); + return SDIOH_API_RC_FAIL; + } ++ + /* For a write, copy the buffer data into the packet. */ +- if (write) +- bcopy(orig_buf, PKTDATA(sd->osh, tmppkt), copylen); +- } ++ if (write) { ++ bcopy(PKTDATA(sd->osh, pkt), ++ PKTDATA(sd->osh, mypkt), ++ PKTLEN(sd->osh, pkt)); ++ } + +- Status = sdioh_request_packet(sd, fix_inc, write, func, addr, tmppkt); ++ Status = sdioh_request_packet(sd, fix_inc, write, func, addr, mypkt); + +- if (copylen) { + /* For a read, copy the packet data back to the buffer. */ +- if (!write) +- bcopy(PKTDATA(sd->osh, tmppkt), orig_buf, PKTLEN(sd->osh, tmppkt)); +- PKTFREE_STATIC(sd->osh, tmppkt, write ? TRUE : FALSE); ++ if (!write) { ++ bcopy(PKTDATA(sd->osh, mypkt), ++ PKTDATA(sd->osh, pkt), ++ PKTLEN(sd->osh, mypkt)); ++ } ++#ifdef CONFIG_DHD_USE_STATIC_BUF ++ PKTFREE_STATIC(sd->osh, mypkt, write ? TRUE : FALSE); ++#else ++ PKTFREE(sd->osh, mypkt, write ? TRUE : FALSE); ++#endif /* CONFIG_DHD_USE_STATIC_BUF */ ++ } else { /* case 3: We have a packet and it is aligned. */ ++ sd_data(("%s: Aligned %s Packet, direct DMA\n", ++ __FUNCTION__, write ? "Tx" : "Rx")); ++ Status = sdioh_request_packet(sd, fix_inc, write, func, addr, pkt); + } + + return (Status); +@@ -1506,10 +1390,7 @@ sdioh_start(sdioh_info_t *si, int stage) + int ret; + sdioh_info_t *sd = gInstance->sd; + +- if (!sd) { +- sd_err(("%s Failed, sd is NULL\n", __FUNCTION__)); +- return (0); +- } ++ if (!sd) return (0); + + /* Need to do this stages as we can't enable the interrupt till + downloading of the firmware is complete, other wise polling +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c linux-sunxi-new/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c +--- linux-sunxi/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c 2014-01-27 01:30:30.100433249 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c 2014-02-15 00:43:44.791014047 +0100 +@@ -1,7 +1,7 @@ + /* + * BCMSDH Function Driver for the native SDIO/MMC driver in the Linux Kernel + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -21,7 +21,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: bcmsdh_sdmmc_linux.c 404103 2013-05-23 20:07:27Z $ ++ * $Id: bcmsdh_sdmmc_linux.c 363783 2012-10-19 06:27:14Z $ + */ + + #include +@@ -110,9 +110,6 @@ static int bcmsdh_sdmmc_probe(struct sdi + int ret = 0; + static struct sdio_func sdio_func_0; + +- if (!gInstance) +- return -EINVAL; +- + if (func) { + sd_trace(("bcmsdh_sdmmc: %s Enter\n", __FUNCTION__)); + sd_trace(("sdio_bcmsdh: func->class=%x\n", func->class)); +@@ -139,8 +136,6 @@ static int bcmsdh_sdmmc_probe(struct sdi + #endif + sd_trace(("F2 found, calling bcmsdh_probe...\n")); + ret = bcmsdh_probe(&func->dev); +- if (ret < 0) +- gInstance->func[2] = NULL; + } + } else { + ret = -ENODEV; +@@ -199,9 +194,11 @@ static int bcmsdh_sdmmc_suspend(struct d + if (func->num != 2) + return 0; + +- sd_trace(("%s Enter\n", __FUNCTION__)); ++ sd_trace_hw4(("%s Enter\n", __FUNCTION__)); ++ + if (dhd_os_check_wakelock(bcmsdh_get_drvdata())) + return -EBUSY; ++ + sdio_flags = sdio_get_host_pm_caps(func); + + if (!(sdio_flags & MMC_PM_KEEP_POWER)) { +@@ -215,9 +212,10 @@ static int bcmsdh_sdmmc_suspend(struct d + sd_err(("%s: error while trying to keep power\n", __FUNCTION__)); + return ret; + } ++ + #if defined(OOB_INTR_ONLY) + bcmsdh_oob_intr_set(0); +-#endif ++#endif /* defined(OOB_INTR_ONLY) */ + dhd_mmc_suspend = TRUE; + smp_mb(); + +@@ -228,14 +226,14 @@ static int bcmsdh_sdmmc_resume(struct de + { + #if defined(OOB_INTR_ONLY) + struct sdio_func *func = dev_to_sdio_func(pdev); +-#endif +- sd_trace(("%s Enter\n", __FUNCTION__)); ++#endif /* defined(OOB_INTR_ONLY) */ ++ sd_trace_hw4(("%s Enter\n", __FUNCTION__)); ++ + dhd_mmc_suspend = FALSE; + #if defined(OOB_INTR_ONLY) + if ((func->num == 2) && dhd_os_check_if_up(bcmsdh_get_drvdata())) + bcmsdh_oob_intr_set(1); +-#endif +- ++#endif /* (OOB_INTR_ONLY) */ + smp_mb(); + return 0; + } +@@ -286,11 +284,13 @@ static struct sdio_driver bcmsdh_sdmmc_d + .remove = bcmsdh_sdmmc_remove, + .name = "bcmsdh_sdmmc", + .id_table = bcmsdh_sdmmc_ids, ++#if !defined(CONFIG_ARCH_RHEA) || !defined(CONFIG_ARCH_CAPRI) + #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM) + .drv = { + .pm = &bcmsdh_sdmmc_pm_ops, + }, + #endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM) */ ++#endif /* !defined(CONFIG_ARCH_RHEA) || !defined(CONFIG_ARCH_CAPRI) */ + }; + + struct sdos_info { +@@ -401,9 +401,9 @@ int sdio_function_init(void) + return -ENOMEM; + + error = sdio_register_driver(&bcmsdh_sdmmc_driver); +- if (error) { ++ if (error && gInstance) { + kfree(gInstance); +- gInstance = NULL; ++ gInstance = 0; + } + + return error; +@@ -420,8 +420,6 @@ void sdio_function_cleanup(void) + + sdio_unregister_driver(&bcmsdh_sdmmc_driver); + +- if (gInstance) { ++ if (gInstance) + kfree(gInstance); +- gInstance = NULL; +- } + } +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/bcmutils.c linux-sunxi-new/drivers/net/wireless/bcmdhd/bcmutils.c +--- linux-sunxi/drivers/net/wireless/bcmdhd/bcmutils.c 2014-01-27 01:30:30.101433269 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/bcmutils.c 2014-02-15 00:43:44.792014069 +0100 +@@ -1,7 +1,7 @@ + /* + * Driver O/S-independent utility routines + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -20,7 +20,7 @@ + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. +- * $Id: bcmutils.c 412804 2013-07-16 16:26:39Z $ ++ * $Id: bcmutils.c 312855 2012-02-04 02:01:18Z $ + */ + + #include +@@ -192,7 +192,7 @@ pktsegcnt_war(osl_t *osh, void *p) + } + + uint8 * BCMFASTPATH +-pktdataoffset(osl_t *osh, void *p, uint offset) ++pktoffset(osl_t *osh, void *p, uint offset) + { + uint total = pkttotlen(osh, p); + uint pkt_off = 0, len = 0; +@@ -211,25 +211,6 @@ pktdataoffset(osl_t *osh, void *p, uint + return (uint8*) (pdata+pkt_off); + } + +- +-/* given a offset in pdata, find the pkt seg hdr */ +-void * +-pktoffset(osl_t *osh, void *p, uint offset) +-{ +- uint total = pkttotlen(osh, p); +- uint len = 0; +- +- if (offset > total) +- return NULL; +- +- for (; p; p = PKTNEXT(osh, p)) { +- len += PKTLEN(osh, p); +- if (len > offset) +- break; +- } +- return p; +-} +- + /* + * osl multiple-precedence packet queue + * hi_prec is always >= the number of the highest non-empty precedence +@@ -343,44 +324,6 @@ pktq_pdeq_prev(struct pktq *pq, int prec + } + + void * BCMFASTPATH +-pktq_pdeq_with_fn(struct pktq *pq, int prec, ifpkt_cb_t fn, int arg) +-{ +- struct pktq_prec *q; +- void *p, *prev = NULL; +- +- ASSERT(prec >= 0 && prec < pq->num_prec); +- +- q = &pq->q[prec]; +- p = q->head; +- +- while (p) { +- if (fn == NULL || (*fn)(p, arg)) { +- break; +- } else { +- prev = p; +- p = PKTLINK(p); +- } +- } +- if (p == NULL) +- return NULL; +- +- if (prev == NULL) { +- if ((q->head = PKTLINK(p)) == NULL) +- q->tail = NULL; +- } else { +- PKTSETLINK(prev, PKTLINK(p)); +- } +- +- q->len--; +- +- pq->len--; +- +- PKTSETLINK(p, NULL); +- +- return p; +-} +- +-void * BCMFASTPATH + pktq_pdeq_tail(struct pktq *pq, int prec) + { + struct pktq_prec *q; +@@ -711,7 +654,6 @@ pktq_mdeq(struct pktq *pq, uint prec_bmp + + #endif /* BCMDRIVER */ + +-#if !defined(BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS) + const unsigned char bcm_ctype[] = { + + _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 0-7 */ +@@ -1025,7 +967,6 @@ bcm_ether_atoe(const char *p, struct eth + + return (i == 6); + } +-#endif /* !BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS */ + + + #if defined(CONFIG_USBRNDIS_RETAIL) || defined(NDIS_MINIPORT_DRIVER) +@@ -1137,7 +1078,7 @@ pktsetprio(void *pkt, bool update_vtag) + + eh = (struct ether_header *) pktdata; + +- if (eh->ether_type == hton16(ETHER_TYPE_8021Q)) { ++ if (ntoh16(eh->ether_type) == ETHER_TYPE_8021Q) { + uint16 vlan_tag; + int vlan_prio, dscp_prio = 0; + +@@ -1146,7 +1087,7 @@ pktsetprio(void *pkt, bool update_vtag) + vlan_tag = ntoh16(evh->vlan_tag); + vlan_prio = (int) (vlan_tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK; + +- if (evh->ether_type == hton16(ETHER_TYPE_IP)) { ++ if (ntoh16(evh->ether_type) == ETHER_TYPE_IP) { + uint8 *ip_body = pktdata + sizeof(struct ethervlan_header); + uint8 tos_tc = IP_TOS46(ip_body); + dscp_prio = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT); +@@ -1173,32 +1114,10 @@ pktsetprio(void *pkt, bool update_vtag) + evh->vlan_tag = hton16(vlan_tag); + rc |= PKTPRIO_UPD; + } +- } else if (eh->ether_type == hton16(ETHER_TYPE_IP)) { ++ } else if (ntoh16(eh->ether_type) == ETHER_TYPE_IP) { + uint8 *ip_body = pktdata + sizeof(struct ether_header); + uint8 tos_tc = IP_TOS46(ip_body); +- uint8 dscp = tos_tc >> IPV4_TOS_DSCP_SHIFT; +- switch (dscp) { +- case DSCP_EF: +- priority = PRIO_8021D_VO; +- break; +- case DSCP_AF31: +- case DSCP_AF32: +- case DSCP_AF33: +- priority = PRIO_8021D_CL; +- break; +- case DSCP_AF21: +- case DSCP_AF22: +- case DSCP_AF23: +- case DSCP_AF11: +- case DSCP_AF12: +- case DSCP_AF13: +- priority = PRIO_8021D_EE; +- break; +- default: +- priority = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT); +- break; +- } +- ++ priority = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT); + rc |= PKTPRIO_DSCP; + } + +@@ -1304,7 +1223,6 @@ bcm_iovar_lencheck(const bcm_iovar_t *vi + #endif /* BCMDRIVER */ + + +-#if !defined(BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS) + /******************************************************************************* + * crc8 + * +@@ -1661,36 +1579,10 @@ bcm_parse_ordered_tlvs(void *buf, int bu + } + return NULL; + } +-#endif /* !BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS */ + + #if defined(WLMSG_PRHDRS) || defined(WLMSG_PRPKT) || defined(WLMSG_ASSOC) || \ + defined(DHD_DEBUG) + int +-bcm_format_field(const bcm_bit_desc_ex_t *bd, uint32 flags, char* buf, int len) +-{ +- int i, slen = 0; +- uint32 bit, mask; +- const char *name; +- mask = bd->mask; +- if (len < 2 || !buf) +- return 0; +- +- buf[0] = '\0'; +- +- for (i = 0; (name = bd->bitfield[i].name) != NULL; i++) { +- bit = bd->bitfield[i].bit; +- if ((flags & mask) == bit) { +- if (len > (int)strlen(name)) { +- slen = strlen(name); +- strncpy(buf, name, slen+1); +- } +- break; +- } +- } +- return slen; +-} +- +-int + bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char* buf, int len) + { + int i; +@@ -1807,6 +1699,9 @@ static const char *crypto_algo_names[] = + "UNDEF", + "UNDEF", + "UNDEF", ++#ifdef BCMWAPI_WPI ++ "WAPI", ++#endif /* BCMWAPI_WPI */ + "UNDEF" + }; + +@@ -2109,39 +2004,6 @@ bcm_print_bytes(const char *name, const + } + printf("\n"); + } +- +-/* Look for vendor-specific IE with specified OUI and optional type */ +-bcm_tlv_t * +-find_vendor_ie(void *tlvs, int tlvs_len, const char *voui, uint8 *type, int type_len) +-{ +- bcm_tlv_t *ie; +- uint8 ie_len; +- +- ie = (bcm_tlv_t*)tlvs; +- +- /* make sure we are looking at a valid IE */ +- if (ie == NULL || +- !bcm_valid_tlv(ie, tlvs_len)) +- return NULL; +- +- /* Walk through the IEs looking for an OUI match */ +- do { +- ie_len = ie->len; +- if ((ie->id == DOT11_MNG_PROPR_ID) && +- (ie_len >= (DOT11_OUI_LEN + type_len)) && +- !bcmp(ie->data, voui, DOT11_OUI_LEN)) +- { +- /* compare optional type */ +- if (type_len == 0 || +- !bcmp(&ie->data[DOT11_OUI_LEN], type, type_len)) { +- return (ie); /* a match */ +- } +- } +- } while ((ie = bcm_next_tlv(ie, &tlvs_len)) != NULL); +- +- return NULL; +-} +- + #if defined(WLTINYDUMP) || defined(WLMSG_INFORM) || defined(WLMSG_ASSOC) || \ + defined(WLMSG_PRPKT) || defined(WLMSG_WSEC) + #define SSID_FMT_BUF_LEN ((4 * DOT11_MAX_SSID_LEN) + 1) +@@ -2229,93 +2091,3 @@ process_nvram_vars(char *varbuf, unsigne + + return buf_len; + } +- +-/* calculate a * b + c */ +-void +-bcm_uint64_multiple_add(uint32* r_high, uint32* r_low, uint32 a, uint32 b, uint32 c) +-{ +-#define FORMALIZE(var) {cc += (var & 0x80000000) ? 1 : 0; var &= 0x7fffffff;} +- uint32 r1, r0; +- uint32 a1, a0, b1, b0, t, cc = 0; +- +- a1 = a >> 16; +- a0 = a & 0xffff; +- b1 = b >> 16; +- b0 = b & 0xffff; +- +- r0 = a0 * b0; +- FORMALIZE(r0); +- +- t = (a1 * b0) << 16; +- FORMALIZE(t); +- +- r0 += t; +- FORMALIZE(r0); +- +- t = (a0 * b1) << 16; +- FORMALIZE(t); +- +- r0 += t; +- FORMALIZE(r0); +- +- FORMALIZE(c); +- +- r0 += c; +- FORMALIZE(r0); +- +- r0 |= (cc % 2) ? 0x80000000 : 0; +- r1 = a1 * b1 + ((a1 * b0) >> 16) + ((b1 * a0) >> 16) + (cc / 2); +- +- *r_high = r1; +- *r_low = r0; +-} +- +-/* calculate a / b */ +-void +-bcm_uint64_divide(uint32* r, uint32 a_high, uint32 a_low, uint32 b) +-{ +- uint32 a1 = a_high, a0 = a_low, r0 = 0; +- +- if (b < 2) +- return; +- +- while (a1 != 0) { +- r0 += (0xffffffff / b) * a1; +- bcm_uint64_multiple_add(&a1, &a0, ((0xffffffff % b) + 1) % b, a1, a0); +- } +- +- r0 += a0 / b; +- *r = r0; +-} +- +-#ifndef setbit /* As in the header file */ +-#ifdef BCMUTILS_BIT_MACROS_USE_FUNCS +-/* Set bit in byte array. */ +-void +-setbit(void *array, uint bit) +-{ +- ((uint8 *)array)[bit / NBBY] |= 1 << (bit % NBBY); +-} +- +-/* Clear bit in byte array. */ +-void +-clrbit(void *array, uint bit) +-{ +- ((uint8 *)array)[bit / NBBY] &= ~(1 << (bit % NBBY)); +-} +- +-/* Test if bit is set in byte array. */ +-bool +-isset(const void *array, uint bit) +-{ +- return (((const uint8 *)array)[bit / NBBY] & (1 << (bit % NBBY))); +-} +- +-/* Test if bit is clear in byte array. */ +-bool +-isclr(const void *array, uint bit) +-{ +- return ((((const uint8 *)array)[bit / NBBY] & (1 << (bit % NBBY))) == 0); +-} +-#endif /* BCMUTILS_BIT_MACROS_USE_FUNCS */ +-#endif /* setbit */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/bcmwifi_channels.c linux-sunxi-new/drivers/net/wireless/bcmdhd/bcmwifi_channels.c +--- linux-sunxi/drivers/net/wireless/bcmdhd/bcmwifi_channels.c 2014-01-27 01:30:30.108433411 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/bcmwifi_channels.c 2014-02-15 00:43:44.795014136 +0100 +@@ -3,7 +3,7 @@ + * Contents are wifi-specific, used by any kernel or app-level + * software that might want wifi things as it grows. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -27,10 +27,10 @@ + + #include + #include +-#include + + #ifdef BCMDRIVER + #include ++#include + #define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base)) + #define tolower(c) (bcm_isupper((c)) ? ((c) + 'a' - 'A') : (c)) + #else +@@ -560,7 +560,7 @@ wf_chspec_aton(const char *a) + return 0; + + /* if we are looking at a 'g', then the first number was a band */ +- c = tolower((int)a[0]); ++ c = tolower(a[0]); + if (c == 'g') { + a ++; /* consume the char */ + +@@ -576,7 +576,7 @@ wf_chspec_aton(const char *a) + if (!read_uint(&a, &ctl_ch)) + return 0; + +- c = tolower((int)a[0]); ++ c = tolower(a[0]); + } + else { + /* first number is channel, use default for band */ +@@ -626,7 +626,7 @@ wf_chspec_aton(const char *a) + * or '+80' if bw = 80, to make '80+80' bw. + */ + +- c = tolower((int)a[0]); ++ c = tolower(a[0]); + + /* if we have a 2g/40 channel, we should have a l/u spec now */ + if (chspec_band == WL_CHANSPEC_BAND_2G && bw == 40) { +@@ -911,12 +911,6 @@ wf_chspec_valid(chanspec_t chanspec) + } + + if (i == num_ch) { +- /* check for channel 165 which is not the side band +- * of 40MHz 5G channel +- */ +- if (chspec_ch == 165) +- i = 0; +- + /* check for legacy JP channels on failure */ + if (chspec_ch == 34 || chspec_ch == 38 || + chspec_ch == 42 || chspec_ch == 46) +@@ -1054,7 +1048,6 @@ wf_channel2chspec(uint ctl_ch, uint bw) + + return chspec; + } +- + #endif /* D11AC_IOTYPES */ + + /* +@@ -1184,106 +1177,3 @@ wf_channel2mhz(uint ch, uint start_facto + + return freq; + } +- +-/* These chan_info[] & lookup routines replicate those from wlc_phy.c because of BMAC split */ +-static const struct chan_info { +- uint16 chan; /* channel number */ +- uint16 freq; /* in MHz */ +-} chan_info[] = { +- /* 11b/11g */ +-/* 0 */ {1, 2412}, +-/* 1 */ {2, 2417}, +-/* 2 */ {3, 2422}, +-/* 3 */ {4, 2427}, +-/* 4 */ {5, 2432}, +-/* 5 */ {6, 2437}, +-/* 6 */ {7, 2442}, +-/* 7 */ {8, 2447}, +-/* 8 */ {9, 2452}, +-/* 9 */ {10, 2457}, +-/* 10 */ {11, 2462}, +-/* 11 */ {12, 2467}, +-/* 12 */ {13, 2472}, +-/* 13 */ {14, 2484}, +- +-#ifdef BAND5G +-/* 11a japan high */ +-/* 14 */ {34, 5170}, +-/* 15 */ {38, 5190}, +-/* 16 */ {42, 5210}, +-/* 17 */ {46, 5230}, +- +-/* 11a usa low */ +-/* 18 */ {36, 5180}, +-/* 19 */ {40, 5200}, +-/* 20 */ {44, 5220}, +-/* 21 */ {48, 5240}, +-/* 22 */ {52, 5260}, +-/* 23 */ {56, 5280}, +-/* 24 */ {60, 5300}, +-/* 25 */ {64, 5320}, +- +-/* 11a Europe */ +-/* 26 */ {100, 5500}, +-/* 27 */ {104, 5520}, +-/* 28 */ {108, 5540}, +-/* 29 */ {112, 5560}, +-/* 30 */ {116, 5580}, +-/* 31 */ {120, 5600}, +-/* 32 */ {124, 5620}, +-/* 33 */ {128, 5640}, +-/* 34 */ {132, 5660}, +-/* 35 */ {136, 5680}, +-/* 36 */ {140, 5700}, +- +-/* 11a usa high, ref5 only */ +-/* 37 */ {149, 5745}, +-/* 38 */ {153, 5765}, +-/* 39 */ {157, 5785}, +-/* 40 */ {161, 5805}, +-/* 41 */ {165, 5825}, +- +-/* 11a japan */ +-/* 42 */ {184, 4920}, +-/* 43 */ {188, 4940}, +-/* 44 */ {192, 4960}, +-/* 45 */ {196, 4980}, +-/* 46 */ {200, 5000}, +-/* 47 */ {204, 5020}, +-/* 48 */ {208, 5040}, +-/* 49 */ {212, 5060}, +-/* 50 */ {216, 5080} +-#endif /* BAND5G */ +-}; +- +-/* +- * Converts channel frequency to channel number. +- * Returns 0 if the frequency does not match any channel definition. +- */ +-uint +-wf_freq2channel(uint freq) +-{ +- uint i; +- +- for (i = 0; i < ARRAYSIZE(chan_info); i++) { +- if (chan_info[i].freq == freq) +- return (chan_info[i].chan); +- } +- return (0); +-} +- +-/* +- * Converts channel number to channel frequency. +- * Returns 0 if the channel is out of range. +- * Also used by some code in wlc_iw.c +- */ +-uint +-wf_channel2freq(uint channel) +-{ +- uint i; +- +- for (i = 0; i < ARRAYSIZE(chan_info); i++) +- if (chan_info[i].chan == channel) +- return (chan_info[i].freq); +- return (0); +-} +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/common/include/proto/802.3.h linux-sunxi-new/drivers/net/wireless/bcmdhd/common/include/proto/802.3.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/common/include/proto/802.3.h 2014-01-27 01:30:30.100433249 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/common/include/proto/802.3.h 2014-02-15 00:43:44.792014069 +0100 +@@ -1,27 +1,15 @@ + /* +- * Copyright (C) 1999-2013, Broadcom Corporation +- * +- * Unless you and Broadcom execute a separate written software license +- * agreement governing use of this software, this software is licensed to you +- * under the terms of the GNU General Public License version 2 (the "GPL"), +- * available at http://www.broadcom.com/licenses/GPLv2.php, with the +- * following added to such license: ++ * Copyright (C) 2013, Broadcom Corporation ++ * All Rights Reserved. + * +- * As a special exception, the copyright holders of this software give you +- * permission to link this software with independent modules, and to copy and +- * distribute the resulting executable under terms of your choice, provided that +- * you also meet, for each linked independent module, the terms and conditions of +- * the license of that module. An independent module is a module which is not +- * derived from this software. The special exception does not apply to any +- * modifications of the software. +- * +- * Notwithstanding the above, under no circumstances may you combine this +- * software in any way with any other Broadcom software provided under a license +- * other than the GPL, without Broadcom's express prior written consent. ++ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; ++ * the contents of this file may not be disclosed to third parties, copied ++ * or duplicated in any form, in whole or in part, without the prior ++ * written permission of Broadcom Corporation. + * + * Fundamental constants relating to 802.3 + * +- * $Id: 802.3.h 417942 2013-08-13 07:53:57Z $ ++ * $Id: 802.3.h 382882 2013-02-04 23:24:31Z $ + */ + + #ifndef _802_3_h_ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/dhd_bta.c linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_bta.c +--- linux-sunxi/drivers/net/wireless/bcmdhd/dhd_bta.c 2014-01-27 01:30:30.109433432 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_bta.c 2014-02-15 00:43:44.796014158 +0100 +@@ -1,7 +1,7 @@ + /* + * BT-AMP support routines + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -21,9 +21,11 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: dhd_bta.c 379512 2013-01-17 22:49:08Z $ ++ * $Id: dhd_bta.c 303834 2011-12-20 06:17:39Z $ + */ ++#ifndef WLBTAMP + #error "WLBTAMP is not defined" ++#endif /* WLBTAMP */ + + #include + #include +@@ -311,9 +313,6 @@ dhd_bta_doevt(dhd_pub_t *dhdp, void *dat + { + amp_hci_event_t *evt = (amp_hci_event_t *)data_buf; + +- ASSERT(dhdp); +- ASSERT(evt); +- + switch (evt->ecode) { + case HCI_Command_Complete: { + cmd_complete_parms_t *parms = (cmd_complete_parms_t *)evt->parms; +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/dhd_bta.h linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_bta.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/dhd_bta.h 2014-01-27 01:30:30.100433249 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_bta.h 2014-02-15 00:43:44.792014069 +0100 +@@ -1,7 +1,7 @@ + /* + * BT-AMP support routines + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/dhd_bus.h linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_bus.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/dhd_bus.h 2014-01-27 01:30:30.101433269 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_bus.h 2014-02-15 00:43:44.792014069 +0100 +@@ -4,7 +4,7 @@ + * Provides type definitions and function prototypes used to link the + * DHD OS, bus, and protocol modules. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -24,7 +24,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: dhd_bus.h 335569 2012-05-29 12:04:43Z $ ++ * $Id: dhd_bus.h 347614 2012-07-27 10:24:51Z $ + */ + + #ifndef _dhd_bus_h_ +@@ -55,7 +55,7 @@ extern void dhd_bus_getidletime(dhd_pub_ + extern void dhd_bus_setidletime(dhd_pub_t *dhdp, int idle_time); + + /* Send a data frame to the dongle. Callee disposes of txp. */ +-extern int dhd_bus_txdata(struct dhd_bus *bus, void *txp); ++extern int dhd_bus_txdata(struct dhd_bus *bus, void *txp, bool wlfc_locked); + + /* Send/receive a control message to/from the dongle. + * Expects caller to enforce a single outstanding transaction. +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/dhd_cdc.c linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_cdc.c +--- linux-sunxi/drivers/net/wireless/bcmdhd/dhd_cdc.c 2014-01-27 01:30:30.100433249 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_cdc.c 2014-02-15 00:43:44.791014047 +0100 +@@ -1,7 +1,7 @@ + /* + * DHD Protocol Module for CDC and BDC. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -21,7 +21,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: dhd_cdc.c 416698 2013-08-06 07:53:34Z $ ++ * $Id: dhd_cdc.c 368762 2012-11-14 21:59:17Z $ + * + * BDC is like CDC, except it includes a header for data packets to convey + * packet priority over the bus, and flags (e.g. to indicate checksum status +@@ -57,6 +57,19 @@ + * round off at the end of buffer + */ + ++#define BUS_RETRIES 1 /* # of retries before aborting a bus tx operation */ ++ ++#ifdef PROP_TXSTATUS ++typedef struct dhd_wlfc_commit_info { ++ uint8 needs_hdr; ++ uint8 ac_fifo_credit_spent; ++ ewlfc_packet_state_t pkt_type; ++ wlfc_mac_descriptor_t* mac_entry; ++ void* p; ++} dhd_wlfc_commit_info_t; ++#endif /* PROP_TXSTATUS */ ++ ++ + typedef struct dhd_prot { + uint16 reqid; + uint8 pending; +@@ -101,14 +114,12 @@ dhdcdc_cmplt(dhd_pub_t *dhd, uint32 id, + + DHD_TRACE(("%s: Enter\n", __FUNCTION__)); + +- + do { + ret = dhd_bus_rxctl(dhd->bus, (uchar*)&prot->msg, cdc_len); + if (ret < 0) + break; + } while (CDC_IOC_ID(ltoh32(prot->msg.flags)) != id); + +- + return ret; + } + +@@ -117,6 +128,7 @@ dhdcdc_query_ioctl(dhd_pub_t *dhd, int i + { + dhd_prot_t *prot = dhd->prot; + cdc_ioctl_t *msg = &prot->msg; ++ void *info; + int ret = 0, retries = 0; + uint32 id, flags = 0; + +@@ -176,12 +188,15 @@ retry: + goto done; + } + ++ /* Check info buffer */ ++ info = (void*)&msg[1]; ++ + /* Copy info buffer */ + if (buf) + { + if (ret < (int)len) + len = ret; +- memcpy(buf, (void*) prot->buf, len); ++ memcpy(buf, info, len); + } + + /* Check the ERROR flag */ +@@ -196,7 +211,6 @@ done: + return ret; + } + +- + static int + dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len, uint8 action) + { +@@ -220,7 +234,6 @@ dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifi + return -EIO; + } + +- + memset(msg, 0, sizeof(cdc_ioctl_t)); + + msg->cmd = htol32(cmd); +@@ -272,11 +285,26 @@ dhd_prot_ioctl(dhd_pub_t *dhd, int ifidx + dhd_prot_t *prot = dhd->prot; + int ret = -1; + uint8 action; ++#if defined(NDIS630) ++ bool acquired = FALSE; ++#endif + + if ((dhd->busstate == DHD_BUS_DOWN) || dhd->hang_was_sent) { + DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__)); + goto done; + } ++#if defined(NDIS630) ++ if (dhd_os_proto_block(dhd)) ++ { ++ acquired = TRUE; ++ } ++ else ++ { ++ /* attempt to acquire protocol mutex timed out. */ ++ ret = -1; ++ return ret; ++ } ++#endif /* NDIS630 */ + + DHD_TRACE(("%s: Enter\n", __FUNCTION__)); + +@@ -327,7 +355,10 @@ dhd_prot_ioctl(dhd_pub_t *dhd, int ifidx + prot->pending = FALSE; + + done: +- ++#if defined(NDIS630) ++ if (acquired) ++ dhd_os_proto_unblock(dhd); ++#endif + return ret; + } + +@@ -338,207 +369,2531 @@ dhd_prot_iovar_op(dhd_pub_t *dhdp, const + return BCME_UNSUPPORTED; + } + ++#ifdef PROP_TXSTATUS + void +-dhd_prot_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf) ++dhd_wlfc_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf) + { +- bcm_bprintf(strbuf, "Protocol CDC: reqid %d\n", dhdp->prot->reqid); +-#ifdef PROP_TXSTATUS +- if (dhdp->wlfc_state) +- dhd_wlfc_dump(dhdp, strbuf); ++ int i; ++ uint8* ea; ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhdp->wlfc_state; ++ wlfc_hanger_t* h; ++ wlfc_mac_descriptor_t* mac_table; ++ wlfc_mac_descriptor_t* interfaces; ++ char* iftypes[] = {"STA", "AP", "WDS", "p2pGO", "p2pCL"}; ++ ++ if (wlfc == NULL) { ++ bcm_bprintf(strbuf, "wlfc not initialized yet\n"); ++ return; ++ } ++ h = (wlfc_hanger_t*)wlfc->hanger; ++ if (h == NULL) { ++ bcm_bprintf(strbuf, "wlfc-hanger not initialized yet\n"); ++ } ++ ++ mac_table = wlfc->destination_entries.nodes; ++ interfaces = wlfc->destination_entries.interfaces; ++ bcm_bprintf(strbuf, "---- wlfc stats ----\n"); ++ if (h) { ++ bcm_bprintf(strbuf, "wlfc hanger (pushed,popped,f_push," ++ "f_pop,f_slot, pending) = (%d,%d,%d,%d,%d,%d)\n", ++ h->pushed, ++ h->popped, ++ h->failed_to_push, ++ h->failed_to_pop, ++ h->failed_slotfind, ++ (h->pushed - h->popped)); ++ } ++ ++ bcm_bprintf(strbuf, "wlfc fail(tlv,credit_rqst,mac_update,psmode_update), " ++ "(dq_full,sendq_full, rollback_fail) = (%d,%d,%d,%d), (%d,%d,%d)\n", ++ wlfc->stats.tlv_parse_failed, ++ wlfc->stats.credit_request_failed, ++ wlfc->stats.mac_update_failed, ++ wlfc->stats.psmode_update_failed, ++ wlfc->stats.delayq_full_error, ++ wlfc->stats.sendq_full_error, ++ wlfc->stats.rollback_failed); ++ ++ bcm_bprintf(strbuf, "SENDQ (len,credit,sent) " ++ "(AC0[%d,%d,%d],AC1[%d,%d,%d],AC2[%d,%d,%d],AC3[%d,%d,%d],BC_MC[%d,%d,%d])\n", ++ wlfc->SENDQ.q[0].len, wlfc->FIFO_credit[0], wlfc->stats.sendq_pkts[0], ++ wlfc->SENDQ.q[1].len, wlfc->FIFO_credit[1], wlfc->stats.sendq_pkts[1], ++ wlfc->SENDQ.q[2].len, wlfc->FIFO_credit[2], wlfc->stats.sendq_pkts[2], ++ wlfc->SENDQ.q[3].len, wlfc->FIFO_credit[3], wlfc->stats.sendq_pkts[3], ++ wlfc->SENDQ.q[4].len, wlfc->FIFO_credit[4], wlfc->stats.sendq_pkts[4]); ++ ++#ifdef PROP_TXSTATUS_DEBUG ++ bcm_bprintf(strbuf, "SENDQ dropped: AC[0-3]:(%d,%d,%d,%d), (bcmc,atim):(%d,%d)\n", ++ wlfc->stats.dropped_qfull[0], wlfc->stats.dropped_qfull[1], ++ wlfc->stats.dropped_qfull[2], wlfc->stats.dropped_qfull[3], ++ wlfc->stats.dropped_qfull[4], wlfc->stats.dropped_qfull[5]); ++#endif ++ ++ bcm_bprintf(strbuf, "\n"); ++ for (i = 0; i < WLFC_MAX_IFNUM; i++) { ++ if (interfaces[i].occupied) { ++ char* iftype_desc; ++ ++ if (interfaces[i].iftype > WLC_E_IF_ROLE_P2P_CLIENT) ++ iftype_desc = "hostif_flow_state[i] == OFF) ++ ? " OFF":" ON")); ++ ++ bcm_bprintf(strbuf, "INTERFACE[%d].DELAYQ(len,state,credit)" ++ "= (%d,%s,%d)\n", ++ i, ++ interfaces[i].psq.len, ++ ((interfaces[i].state == ++ WLFC_STATE_OPEN) ? " OPEN":"CLOSE"), ++ interfaces[i].requested_credit); ++ ++ bcm_bprintf(strbuf, "INTERFACE[%d].DELAYQ" ++ "(sup,ac0),(sup,ac1),(sup,ac2),(sup,ac3) = " ++ "(%d,%d),(%d,%d),(%d,%d),(%d,%d)\n", ++ i, ++ interfaces[i].psq.q[0].len, ++ interfaces[i].psq.q[1].len, ++ interfaces[i].psq.q[2].len, ++ interfaces[i].psq.q[3].len, ++ interfaces[i].psq.q[4].len, ++ interfaces[i].psq.q[5].len, ++ interfaces[i].psq.q[6].len, ++ interfaces[i].psq.q[7].len); ++ } ++ } ++ ++ bcm_bprintf(strbuf, "\n"); ++ for (i = 0; i < WLFC_MAC_DESC_TABLE_SIZE; i++) { ++ if (mac_table[i].occupied) { ++ ea = mac_table[i].ea; ++ bcm_bprintf(strbuf, "MAC_table[%d].ea = " ++ "[%02x:%02x:%02x:%02x:%02x:%02x], if:%d \n", i, ++ ea[0], ea[1], ea[2], ea[3], ea[4], ea[5], ++ mac_table[i].interface_id); ++ ++ bcm_bprintf(strbuf, "MAC_table[%d].DELAYQ(len,state,credit)" ++ "= (%d,%s,%d)\n", ++ i, ++ mac_table[i].psq.len, ++ ((mac_table[i].state == ++ WLFC_STATE_OPEN) ? " OPEN":"CLOSE"), ++ mac_table[i].requested_credit); ++#ifdef PROP_TXSTATUS_DEBUG ++ bcm_bprintf(strbuf, "MAC_table[%d]: (opened, closed) = (%d, %d)\n", ++ i, mac_table[i].opened_ct, mac_table[i].closed_ct); + #endif ++ bcm_bprintf(strbuf, "MAC_table[%d].DELAYQ" ++ "(sup,ac0),(sup,ac1),(sup,ac2),(sup,ac3) = " ++ "(%d,%d),(%d,%d),(%d,%d),(%d,%d)\n", ++ i, ++ mac_table[i].psq.q[0].len, ++ mac_table[i].psq.q[1].len, ++ mac_table[i].psq.q[2].len, ++ mac_table[i].psq.q[3].len, ++ mac_table[i].psq.q[4].len, ++ mac_table[i].psq.q[5].len, ++ mac_table[i].psq.q[6].len, ++ mac_table[i].psq.q[7].len); ++ } ++ } ++ ++#ifdef PROP_TXSTATUS_DEBUG ++ { ++ int avg; ++ int moving_avg = 0; ++ int moving_samples; ++ ++ if (wlfc->stats.latency_sample_count) { ++ moving_samples = sizeof(wlfc->stats.deltas)/sizeof(uint32); ++ ++ for (i = 0; i < moving_samples; i++) ++ moving_avg += wlfc->stats.deltas[i]; ++ moving_avg /= moving_samples; ++ ++ avg = (100 * wlfc->stats.total_status_latency) / ++ wlfc->stats.latency_sample_count; ++ bcm_bprintf(strbuf, "txstatus latency (average, last, moving[%d]) = " ++ "(%d.%d, %03d, %03d)\n", ++ moving_samples, avg/100, (avg - (avg/100)*100), ++ wlfc->stats.latency_most_recent, ++ moving_avg); ++ } ++ } ++ ++ bcm_bprintf(strbuf, "wlfc- fifo[0-5] credit stats: sent = (%d,%d,%d,%d,%d,%d), " ++ "back = (%d,%d,%d,%d,%d,%d)\n", ++ wlfc->stats.fifo_credits_sent[0], ++ wlfc->stats.fifo_credits_sent[1], ++ wlfc->stats.fifo_credits_sent[2], ++ wlfc->stats.fifo_credits_sent[3], ++ wlfc->stats.fifo_credits_sent[4], ++ wlfc->stats.fifo_credits_sent[5], ++ ++ wlfc->stats.fifo_credits_back[0], ++ wlfc->stats.fifo_credits_back[1], ++ wlfc->stats.fifo_credits_back[2], ++ wlfc->stats.fifo_credits_back[3], ++ wlfc->stats.fifo_credits_back[4], ++ wlfc->stats.fifo_credits_back[5]); ++ { ++ uint32 fifo_cr_sent = 0; ++ uint32 fifo_cr_acked = 0; ++ uint32 request_cr_sent = 0; ++ uint32 request_cr_ack = 0; ++ uint32 bc_mc_cr_ack = 0; ++ ++ for (i = 0; i < sizeof(wlfc->stats.fifo_credits_sent)/sizeof(uint32); i++) { ++ fifo_cr_sent += wlfc->stats.fifo_credits_sent[i]; ++ } ++ ++ for (i = 0; i < sizeof(wlfc->stats.fifo_credits_back)/sizeof(uint32); i++) { ++ fifo_cr_acked += wlfc->stats.fifo_credits_back[i]; ++ } ++ ++ for (i = 0; i < WLFC_MAC_DESC_TABLE_SIZE; i++) { ++ if (wlfc->destination_entries.nodes[i].occupied) { ++ request_cr_sent += ++ wlfc->destination_entries.nodes[i].dstncredit_sent_packets; ++ } ++ } ++ for (i = 0; i < WLFC_MAX_IFNUM; i++) { ++ if (wlfc->destination_entries.interfaces[i].occupied) { ++ request_cr_sent += ++ wlfc->destination_entries.interfaces[i].dstncredit_sent_packets; ++ } ++ } ++ for (i = 0; i < WLFC_MAC_DESC_TABLE_SIZE; i++) { ++ if (wlfc->destination_entries.nodes[i].occupied) { ++ request_cr_ack += ++ wlfc->destination_entries.nodes[i].dstncredit_acks; ++ } ++ } ++ for (i = 0; i < WLFC_MAX_IFNUM; i++) { ++ if (wlfc->destination_entries.interfaces[i].occupied) { ++ request_cr_ack += ++ wlfc->destination_entries.interfaces[i].dstncredit_acks; ++ } ++ } ++ bcm_bprintf(strbuf, "wlfc- (sent, status) => pq(%d,%d), vq(%d,%d)," ++ "other:%d, bc_mc:%d, signal-only, (sent,freed): (%d,%d)", ++ fifo_cr_sent, fifo_cr_acked, ++ request_cr_sent, request_cr_ack, ++ wlfc->destination_entries.other.dstncredit_acks, ++ bc_mc_cr_ack, ++ wlfc->stats.signal_only_pkts_sent, wlfc->stats.signal_only_pkts_freed); ++ } ++#endif /* PROP_TXSTATUS_DEBUG */ ++ bcm_bprintf(strbuf, "\n"); ++ bcm_bprintf(strbuf, "wlfc- pkt((in,2bus,txstats,hdrpull),(dropped,hdr_only,wlc_tossed)" ++ "(freed,free_err,rollback)) = " ++ "((%d,%d,%d,%d),(%d,%d,%d),(%d,%d,%d))\n", ++ wlfc->stats.pktin, ++ wlfc->stats.pkt2bus, ++ wlfc->stats.txstatus_in, ++ wlfc->stats.dhd_hdrpulls, ++ ++ wlfc->stats.pktdropped, ++ wlfc->stats.wlfc_header_only_pkt, ++ wlfc->stats.wlc_tossed_pkts, ++ ++ wlfc->stats.pkt_freed, ++ wlfc->stats.pkt_free_err, wlfc->stats.rollback); ++ ++ bcm_bprintf(strbuf, "wlfc- suppress((d11,wlc,err),enq(d11,wl,hq,mac?),retx(d11,wlc,hq)) = " ++ "((%d,%d,%d),(%d,%d,%d,%d),(%d,%d,%d))\n", ++ ++ wlfc->stats.d11_suppress, ++ wlfc->stats.wl_suppress, ++ wlfc->stats.bad_suppress, ++ ++ wlfc->stats.psq_d11sup_enq, ++ wlfc->stats.psq_wlsup_enq, ++ wlfc->stats.psq_hostq_enq, ++ wlfc->stats.mac_handle_notfound, ++ ++ wlfc->stats.psq_d11sup_retx, ++ wlfc->stats.psq_wlsup_retx, ++ wlfc->stats.psq_hostq_retx); ++ return; + } + +-/* The FreeBSD PKTPUSH could change the packet buf pinter +- so we need to make it changable ++/* Create a place to store all packet pointers submitted to the firmware until ++ a status comes back, suppress or otherwise. ++ ++ hang-er: noun, a contrivance on which things are hung, as a hook. + */ +-#define PKTBUF pktbuf +-void +-dhd_prot_hdrpush(dhd_pub_t *dhd, int ifidx, void *PKTBUF) ++static void* ++dhd_wlfc_hanger_create(osl_t *osh, int max_items) + { +-#ifdef BDC +- struct bdc_header *h; +-#endif /* BDC */ +- +- DHD_TRACE(("%s: Enter\n", __FUNCTION__)); ++ int i; ++ wlfc_hanger_t* hanger; + +-#ifdef BDC +- /* Push BDC header used to convey priority for buses that don't */ ++ /* allow only up to a specific size for now */ ++ ASSERT(max_items == WLFC_HANGER_MAXITEMS); + +- PKTPUSH(dhd->osh, PKTBUF, BDC_HEADER_LEN); ++ if ((hanger = (wlfc_hanger_t*)MALLOC(osh, WLFC_HANGER_SIZE(max_items))) == NULL) ++ return NULL; + +- h = (struct bdc_header *)PKTDATA(dhd->osh, PKTBUF); ++ memset(hanger, 0, WLFC_HANGER_SIZE(max_items)); ++ hanger->max_items = max_items; + +- h->flags = (BDC_PROTO_VER << BDC_FLAG_VER_SHIFT); +- if (PKTSUMNEEDED(PKTBUF)) +- h->flags |= BDC_FLAG_SUM_NEEDED; ++ for (i = 0; i < hanger->max_items; i++) { ++ hanger->items[i].state = WLFC_HANGER_ITEM_STATE_FREE; ++ } ++ return hanger; ++} + ++static int ++dhd_wlfc_hanger_delete(osl_t *osh, void* hanger) ++{ ++ wlfc_hanger_t* h = (wlfc_hanger_t*)hanger; + +- h->priority = (PKTPRIO(PKTBUF) & BDC_PRIORITY_MASK); +- h->flags2 = 0; +- h->dataOffset = 0; +-#endif /* BDC */ +- BDC_SET_IF_IDX(h, ifidx); ++ if (h) { ++ MFREE(osh, h, WLFC_HANGER_SIZE(h->max_items)); ++ return BCME_OK; ++ } ++ return BCME_BADARG; + } +-#undef PKTBUF /* Only defined in the above routine */ + +-int +-dhd_prot_hdrpull(dhd_pub_t *dhd, int *ifidx, void *pktbuf, uchar *reorder_buf_info, +- uint *reorder_info_len) ++static uint16 ++dhd_wlfc_hanger_get_free_slot(void* hanger) + { +-#ifdef BDC +- struct bdc_header *h; +-#endif +- uint8 data_offset = 0; ++ uint32 i; ++ wlfc_hanger_t* h = (wlfc_hanger_t*)hanger; + +- DHD_TRACE(("%s: Enter\n", __FUNCTION__)); ++ if (h) { ++ for (i = (h->slot_pos + 1); i != h->slot_pos;) { ++ if (h->items[i].state == WLFC_HANGER_ITEM_STATE_FREE) { ++ h->slot_pos = i; ++ return (uint16)i; ++ } ++ (i == h->max_items)? i = 0 : i++; ++ } ++ h->failed_slotfind++; ++ } ++ return WLFC_HANGER_MAXITEMS; ++} + +-#ifdef BDC +- if (reorder_info_len) +- *reorder_info_len = 0; +- /* Pop BDC header used to convey priority for buses that don't */ ++static int ++dhd_wlfc_hanger_get_genbit(void* hanger, void* pkt, uint32 slot_id, int* gen) ++{ ++ int rc = BCME_OK; ++ wlfc_hanger_t* h = (wlfc_hanger_t*)hanger; + +- if (PKTLEN(dhd->osh, pktbuf) < BDC_HEADER_LEN) { +- DHD_ERROR(("%s: rx data too short (%d < %d)\n", __FUNCTION__, +- PKTLEN(dhd->osh, pktbuf), BDC_HEADER_LEN)); +- return BCME_ERROR; ++ *gen = 0xff; ++ ++ /* this packet was not pushed at the time it went to the firmware */ ++ if (slot_id == WLFC_HANGER_MAXITEMS) ++ return BCME_NOTFOUND; ++ ++ if (h) { ++ if ((h->items[slot_id].state == WLFC_HANGER_ITEM_STATE_INUSE) || ++ (h->items[slot_id].state == WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED)) { ++ *gen = h->items[slot_id].gen; ++ } ++ else { ++ rc = BCME_NOTFOUND; ++ } + } ++ else ++ rc = BCME_BADARG; ++ return rc; ++} + +- h = (struct bdc_header *)PKTDATA(dhd->osh, pktbuf); ++static int ++dhd_wlfc_hanger_pushpkt(void* hanger, void* pkt, uint32 slot_id) ++{ ++ int rc = BCME_OK; ++ wlfc_hanger_t* h = (wlfc_hanger_t*)hanger; + +- if (!ifidx) { +- /* for tx packet, skip the analysis */ +- data_offset = h->dataOffset; +- PKTPULL(dhd->osh, pktbuf, BDC_HEADER_LEN); +- goto exit; ++ if (h && (slot_id < WLFC_HANGER_MAXITEMS)) { ++ if (h->items[slot_id].state == WLFC_HANGER_ITEM_STATE_FREE) { ++ h->items[slot_id].state = WLFC_HANGER_ITEM_STATE_INUSE; ++ h->items[slot_id].pkt = pkt; ++ h->items[slot_id].identifier = slot_id; ++ h->pushed++; ++ } ++ else { ++ h->failed_to_push++; ++ rc = BCME_NOTFOUND; ++ } + } ++ else ++ rc = BCME_BADARG; ++ return rc; ++} + +- if ((*ifidx = BDC_GET_IF_IDX(h)) >= DHD_MAX_IFS) { +- DHD_ERROR(("%s: rx data ifnum out of range (%d)\n", +- __FUNCTION__, *ifidx)); +- return BCME_ERROR; ++static int ++dhd_wlfc_hanger_poppkt(void* hanger, uint32 slot_id, void** pktout, int remove_from_hanger) ++{ ++ int rc = BCME_OK; ++ wlfc_hanger_t* h = (wlfc_hanger_t*)hanger; ++ ++ /* this packet was not pushed at the time it went to the firmware */ ++ if (slot_id == WLFC_HANGER_MAXITEMS) ++ return BCME_NOTFOUND; ++ ++ if (h) { ++ if (h->items[slot_id].state != WLFC_HANGER_ITEM_STATE_FREE) { ++ *pktout = h->items[slot_id].pkt; ++ if (remove_from_hanger) { ++ h->items[slot_id].state = ++ WLFC_HANGER_ITEM_STATE_FREE; ++ h->items[slot_id].pkt = NULL; ++ h->items[slot_id].identifier = 0; ++ h->items[slot_id].gen = 0xff; ++ h->popped++; ++ } ++ } ++ else { ++ h->failed_to_pop++; ++ rc = BCME_NOTFOUND; ++ } + } ++ else ++ rc = BCME_BADARG; ++ return rc; ++} + +- 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)); +- if (((h->flags & BDC_FLAG_VER_MASK) >> BDC_FLAG_VER_SHIFT) == BDC_PROTO_VER_1) +- h->dataOffset = 0; ++static int ++dhd_wlfc_hanger_mark_suppressed(void* hanger, uint32 slot_id, uint8 gen) ++{ ++ int rc = BCME_OK; ++ wlfc_hanger_t* h = (wlfc_hanger_t*)hanger; ++ ++ /* this packet was not pushed at the time it went to the firmware */ ++ if (slot_id == WLFC_HANGER_MAXITEMS) ++ return BCME_NOTFOUND; ++ if (h) { ++ h->items[slot_id].gen = gen; ++ if (h->items[slot_id].state == WLFC_HANGER_ITEM_STATE_INUSE) { ++ h->items[slot_id].state = WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED; ++ } + else +- return BCME_ERROR; ++ rc = BCME_BADARG; + } ++ else ++ rc = BCME_BADARG; + +- 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); ++ return rc; ++} ++ ++static int ++_dhd_wlfc_pushheader(athost_wl_status_info_t* ctx, void* p, bool tim_signal, ++ uint8 tim_bmp, uint8 mac_handle, uint32 htodtag) ++{ ++ uint32 wl_pktinfo = 0; ++ uint8* wlh; ++ uint8 dataOffset; ++ uint8 fillers; ++ uint8 tim_signal_len = 0; ++ ++ struct bdc_header *h; ++ ++ if (tim_signal) { ++ tim_signal_len = 1 + 1 + WLFC_CTL_VALUE_LEN_PENDING_TRAFFIC_BMP; + } + +- PKTSETPRIO(pktbuf, (h->priority & BDC_PRIORITY_MASK)); +- data_offset = h->dataOffset; +- PKTPULL(dhd->osh, pktbuf, BDC_HEADER_LEN); +-#endif /* BDC */ ++ /* +2 is for Type[1] and Len[1] in TLV, plus TIM signal */ ++ dataOffset = WLFC_CTL_VALUE_LEN_PKTTAG + 2 + tim_signal_len; ++ fillers = ROUNDUP(dataOffset, 4) - dataOffset; ++ dataOffset += fillers; + +-#ifdef PROP_TXSTATUS +- dhd_os_wlfc_block(dhd); +- if (dhd->wlfc_state && +- ((athost_wl_status_info_t*)dhd->wlfc_state)->proptxstatus_mode +- != WLFC_FCMODE_NONE && +- (!DHD_PKTTAG_PKTDIR(PKTTAG(pktbuf)))) { +- /* +- - parse txstatus only for packets that came from the firmware +- */ +- dhd_wlfc_parse_header_info(dhd, pktbuf, (data_offset << 2), +- reorder_buf_info, reorder_info_len); +- ((athost_wl_status_info_t*)dhd->wlfc_state)->stats.dhd_hdrpulls++; ++ PKTPUSH(ctx->osh, p, dataOffset); ++ wlh = (uint8*) PKTDATA(ctx->osh, p); ++ ++ wl_pktinfo = htol32(htodtag); + ++ wlh[0] = WLFC_CTL_TYPE_PKTTAG; ++ wlh[1] = WLFC_CTL_VALUE_LEN_PKTTAG; ++ memcpy(&wlh[2], &wl_pktinfo, sizeof(uint32)); ++ ++ if (tim_signal_len) { ++ wlh[dataOffset - fillers - tim_signal_len ] = ++ WLFC_CTL_TYPE_PENDING_TRAFFIC_BMP; ++ wlh[dataOffset - fillers - tim_signal_len + 1] = ++ WLFC_CTL_VALUE_LEN_PENDING_TRAFFIC_BMP; ++ wlh[dataOffset - fillers - tim_signal_len + 2] = mac_handle; ++ wlh[dataOffset - fillers - tim_signal_len + 3] = tim_bmp; + } +- dhd_os_wlfc_unblock(dhd); +-#endif /* PROP_TXSTATUS */ ++ if (fillers) ++ memset(&wlh[dataOffset - fillers], WLFC_CTL_TYPE_FILLER, fillers); + +-exit: +- PKTPULL(dhd->osh, pktbuf, (data_offset << 2)); +- return 0; ++ PKTPUSH(ctx->osh, p, BDC_HEADER_LEN); ++ h = (struct bdc_header *)PKTDATA(ctx->osh, p); ++ h->flags = (BDC_PROTO_VER << BDC_FLAG_VER_SHIFT); ++ if (PKTSUMNEEDED(p)) ++ h->flags |= BDC_FLAG_SUM_NEEDED; ++ ++ ++ h->priority = (PKTPRIO(p) & BDC_PRIORITY_MASK); ++ h->flags2 = 0; ++ h->dataOffset = dataOffset >> 2; ++ BDC_SET_IF_IDX(h, DHD_PKTTAG_IF(PKTTAG(p))); ++ return BCME_OK; + } + +-#if defined(PROP_TXSTATUS) +-void +-dhd_wlfc_trigger_pktcommit(dhd_pub_t *dhd) ++static int ++_dhd_wlfc_pullheader(athost_wl_status_info_t* ctx, void* pktbuf) + { +- dhd_os_wlfc_block(dhd); +- if (dhd->wlfc_state && +- (((athost_wl_status_info_t*)dhd->wlfc_state)->proptxstatus_mode +- != WLFC_FCMODE_NONE)) { +- dhd_wlfc_commit_packets(dhd->wlfc_state, (f_commitpkt_t)dhd_bus_txdata, +- (void *)dhd->bus, NULL); ++ struct bdc_header *h; ++ ++ if (PKTLEN(ctx->osh, pktbuf) < BDC_HEADER_LEN) { ++ WLFC_DBGMESG(("%s: rx data too short (%d < %d)\n", __FUNCTION__, ++ PKTLEN(ctx->osh, pktbuf), BDC_HEADER_LEN)); ++ return BCME_ERROR; + } +- dhd_os_wlfc_unblock(dhd); ++ h = (struct bdc_header *)PKTDATA(ctx->osh, pktbuf); ++ ++ /* pull BDC header */ ++ PKTPULL(ctx->osh, pktbuf, BDC_HEADER_LEN); ++ ++ if (PKTLEN(ctx->osh, pktbuf) < (h->dataOffset << 2)) { ++ WLFC_DBGMESG(("%s: rx data too short (%d < %d)\n", __FUNCTION__, ++ PKTLEN(ctx->osh, pktbuf), (h->dataOffset << 2))); ++ return BCME_ERROR; ++ } ++ /* pull wl-header */ ++ PKTPULL(ctx->osh, pktbuf, (h->dataOffset << 2)); ++ return BCME_OK; + } +-#endif + ++static wlfc_mac_descriptor_t* ++_dhd_wlfc_find_table_entry(athost_wl_status_info_t* ctx, void* p) ++{ ++ int i; ++ wlfc_mac_descriptor_t* table = ctx->destination_entries.nodes; ++ uint8 ifid = DHD_PKTTAG_IF(PKTTAG(p)); ++ uint8* dstn = DHD_PKTTAG_DSTN(PKTTAG(p)); ++ ++ if (((ctx->destination_entries.interfaces[ifid].iftype == WLC_E_IF_ROLE_STA) || ++ ETHER_ISMULTI(dstn) || ++ (ctx->destination_entries.interfaces[ifid].iftype == WLC_E_IF_ROLE_P2P_CLIENT)) && ++ (ctx->destination_entries.interfaces[ifid].occupied)) { ++ return &ctx->destination_entries.interfaces[ifid]; ++ } ++ ++ for (i = 0; i < WLFC_MAC_DESC_TABLE_SIZE; i++) { ++ if (table[i].occupied) { ++ if (table[i].interface_id == ifid) { ++ if (!memcmp(table[i].ea, dstn, ETHER_ADDR_LEN)) ++ return &table[i]; ++ } ++ } ++ } ++ return &ctx->destination_entries.other; ++} + +-int +-dhd_prot_attach(dhd_pub_t *dhd) ++static int ++_dhd_wlfc_rollback_packet_toq(athost_wl_status_info_t* ctx, ++ void* p, ewlfc_packet_state_t pkt_type, uint32 hslot) + { +- dhd_prot_t *cdc; ++ /* ++ put the packet back to the head of queue + +- if (!(cdc = (dhd_prot_t *)DHD_OS_PREALLOC(dhd->osh, DHD_PREALLOC_PROT, +- sizeof(dhd_prot_t)))) { +- DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__)); +- goto fail; ++ - a packet from send-q will need to go back to send-q and not delay-q ++ since that will change the order of packets. ++ - suppressed packet goes back to suppress sub-queue ++ - pull out the header, if new or delayed packet ++ ++ Note: hslot is used only when header removal is done. ++ */ ++ wlfc_mac_descriptor_t* entry; ++ void* pktout; ++ int rc = BCME_OK; ++ int prec; ++ ++ entry = _dhd_wlfc_find_table_entry(ctx, p); ++ prec = DHD_PKTTAG_FIFO(PKTTAG(p)); ++ if (entry != NULL) { ++ if (pkt_type == eWLFC_PKTTYPE_SUPPRESSED) { ++ /* wl-header is saved for suppressed packets */ ++ if (WLFC_PKTQ_PENQ_HEAD(&entry->psq, ((prec << 1) + 1), p) == NULL) { ++ WLFC_DBGMESG(("Error: %s():%d\n", __FUNCTION__, __LINE__)); ++ rc = BCME_ERROR; ++ } + } +- memset(cdc, 0, sizeof(dhd_prot_t)); ++ else { ++ /* remove header first */ ++ rc = _dhd_wlfc_pullheader(ctx, p); ++ if (rc != BCME_OK) { ++ WLFC_DBGMESG(("Error: %s():%d\n", __FUNCTION__, __LINE__)); ++ /* free the hanger slot */ ++ dhd_wlfc_hanger_poppkt(ctx->hanger, hslot, &pktout, 1); ++ PKTFREE(ctx->osh, p, TRUE); ++ rc = BCME_ERROR; ++ return rc; ++ } ++ ++ if (pkt_type == eWLFC_PKTTYPE_DELAYED) { ++ /* delay-q packets are going to delay-q */ ++ if (WLFC_PKTQ_PENQ_HEAD(&entry->psq, (prec << 1), p) == NULL) { ++ WLFC_DBGMESG(("Error: %s():%d\n", __FUNCTION__, __LINE__)); ++ rc = BCME_ERROR; ++ } ++ } ++ else { ++ /* these are going to SENDQ */ ++ if (WLFC_PKTQ_PENQ_HEAD(&ctx->SENDQ, prec, p) == NULL) { ++ WLFC_DBGMESG(("Error: %s():%d\n", __FUNCTION__, __LINE__)); ++ rc = BCME_ERROR; ++ } ++ } ++ /* free the hanger slot */ ++ dhd_wlfc_hanger_poppkt(ctx->hanger, hslot, &pktout, 1); + +- /* ensure that the msg buf directly follows the cdc msg struct */ +- if ((uintptr)(&cdc->msg + 1) != (uintptr)cdc->buf) { +- DHD_ERROR(("dhd_prot_t is not correctly defined\n")); +- goto fail; ++ /* decrement sequence count */ ++ WLFC_DECR_SEQCOUNT(entry, prec); ++ } ++ /* ++ if this packet did not count against FIFO credit, it must have ++ taken a requested_credit from the firmware (for pspoll etc.) ++ */ ++ if (!DHD_PKTTAG_CREDITCHECK(PKTTAG(p))) { ++ entry->requested_credit++; ++ } + } ++ else { ++ WLFC_DBGMESG(("Error: %s():%d\n", __FUNCTION__, __LINE__)); ++ rc = BCME_ERROR; ++ } ++ if (rc != BCME_OK) ++ ctx->stats.rollback_failed++; ++ else ++ ctx->stats.rollback++; + +- 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: +-#ifndef CONFIG_DHD_USE_STATIC_BUF +- if (cdc != NULL) +- MFREE(dhd->osh, cdc, sizeof(dhd_prot_t)); +-#endif /* CONFIG_DHD_USE_STATIC_BUF */ +- return BCME_NOMEM; ++ return rc; + } + +-/* ~NOTE~ What if another thread is waiting on the semaphore? Holding it? */ +-void +-dhd_prot_detach(dhd_pub_t *dhd) ++static void ++_dhd_wlfc_flow_control_check(athost_wl_status_info_t* ctx, struct pktq* pq, uint8 if_id) + { +-#ifdef PROP_TXSTATUS +- dhd_wlfc_deinit(dhd); +- if (dhd->plat_deinit) +- dhd->plat_deinit((void *)dhd); +-#endif +-#ifndef CONFIG_DHD_USE_STATIC_BUF +- MFREE(dhd->osh, dhd->prot, sizeof(dhd_prot_t)); +-#endif /* CONFIG_DHD_USE_STATIC_BUF */ +- dhd->prot = NULL; ++ if ((pq->len <= WLFC_FLOWCONTROL_LOWATER) && (ctx->hostif_flow_state[if_id] == ON)) { ++ /* start traffic */ ++ ctx->hostif_flow_state[if_id] = OFF; ++ /* ++ WLFC_DBGMESG(("qlen:%02d, if:%02d, ->OFF, start traffic %s()\n", ++ pq->len, if_id, __FUNCTION__)); ++ */ ++ WLFC_DBGMESG(("F")); ++ dhd_txflowcontrol(ctx->dhdp, if_id, OFF); ++ ctx->toggle_host_if = 0; ++ } ++ if ((pq->len >= WLFC_FLOWCONTROL_HIWATER) && (ctx->hostif_flow_state[if_id] == OFF)) { ++ /* stop traffic */ ++ ctx->hostif_flow_state[if_id] = ON; ++ /* ++ WLFC_DBGMESG(("qlen:%02d, if:%02d, ->ON, stop traffic %s()\n", ++ pq->len, if_id, __FUNCTION__)); ++ */ ++ WLFC_DBGMESG(("N")); ++ dhd_txflowcontrol(ctx->dhdp, if_id, ON); ++ ctx->host_ifidx = if_id; ++ ctx->toggle_host_if = 1; ++ } ++ return; + } + +-void +-dhd_prot_dstats(dhd_pub_t *dhd) ++static int ++_dhd_wlfc_send_signalonly_packet(athost_wl_status_info_t* ctx, wlfc_mac_descriptor_t* entry, ++ uint8 ta_bmp) + { +- /* 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 rc = BCME_OK; ++ void* p = NULL; ++ int dummylen = ((dhd_pub_t *)ctx->dhdp)->hdrlen+ 12; ++ ++ /* allocate a dummy packet */ ++ p = PKTGET(ctx->osh, dummylen, TRUE); ++ if (p) { ++ PKTPULL(ctx->osh, p, dummylen); ++ DHD_PKTTAG_SET_H2DTAG(PKTTAG(p), 0); ++ _dhd_wlfc_pushheader(ctx, p, TRUE, ta_bmp, entry->mac_handle, 0); ++ DHD_PKTTAG_SETSIGNALONLY(PKTTAG(p), 1); ++#ifdef PROP_TXSTATUS_DEBUG ++ ctx->stats.signal_only_pkts_sent++; ++#endif ++ rc = dhd_bus_txdata(((dhd_pub_t *)ctx->dhdp)->bus, p, FALSE); ++ if (rc != BCME_OK) { ++ PKTFREE(ctx->osh, p, TRUE); ++ } ++ } ++ else { ++ DHD_ERROR(("%s: couldn't allocate new %d-byte packet\n", ++ __FUNCTION__, dummylen)); ++ rc = BCME_NOMEM; ++ } ++ return rc; + } + +-int +-dhd_prot_init(dhd_pub_t *dhd) ++/* Return TRUE if traffic availability changed */ ++static bool ++_dhd_wlfc_traffic_pending_check(athost_wl_status_info_t* ctx, wlfc_mac_descriptor_t* entry, ++ int prec) ++{ ++ bool rc = FALSE; ++ ++ if (entry->state == WLFC_STATE_CLOSE) { ++ if ((pktq_plen(&entry->psq, (prec << 1)) == 0) && ++ (pktq_plen(&entry->psq, ((prec << 1) + 1)) == 0)) { ++ ++ if (entry->traffic_pending_bmp & NBITVAL(prec)) { ++ rc = TRUE; ++ entry->traffic_pending_bmp = ++ entry->traffic_pending_bmp & ~ NBITVAL(prec); ++ } ++ } ++ else { ++ if (!(entry->traffic_pending_bmp & NBITVAL(prec))) { ++ rc = TRUE; ++ entry->traffic_pending_bmp = ++ entry->traffic_pending_bmp | NBITVAL(prec); ++ } ++ } ++ } ++ if (rc) { ++ /* request a TIM update to firmware at the next piggyback opportunity */ ++ if (entry->traffic_lastreported_bmp != entry->traffic_pending_bmp) { ++ entry->send_tim_signal = 1; ++ _dhd_wlfc_send_signalonly_packet(ctx, entry, entry->traffic_pending_bmp); ++ entry->traffic_lastreported_bmp = entry->traffic_pending_bmp; ++ entry->send_tim_signal = 0; ++ } ++ else { ++ rc = FALSE; ++ } ++ } ++ return rc; ++} ++ ++static int ++_dhd_wlfc_enque_suppressed(athost_wl_status_info_t* ctx, int prec, void* p) ++{ ++ wlfc_mac_descriptor_t* entry; ++ ++ entry = _dhd_wlfc_find_table_entry(ctx, p); ++ if (entry == NULL) { ++ WLFC_DBGMESG(("Error: %s():%d\n", __FUNCTION__, __LINE__)); ++ return BCME_NOTFOUND; ++ } ++ /* ++ - suppressed packets go to sub_queue[2*prec + 1] AND ++ - delayed packets go to sub_queue[2*prec + 0] to ensure ++ order of delivery. ++ */ ++ if (WLFC_PKTQ_PENQ(&entry->psq, ((prec << 1) + 1), p) == NULL) { ++ ctx->stats.delayq_full_error++; ++ /* WLFC_DBGMESG(("Error: %s():%d\n", __FUNCTION__, __LINE__)); */ ++ WLFC_DBGMESG(("s")); ++ return BCME_ERROR; ++ } ++ /* A packet has been pushed, update traffic availability bitmap, if applicable */ ++ _dhd_wlfc_traffic_pending_check(ctx, entry, prec); ++ _dhd_wlfc_flow_control_check(ctx, &entry->psq, DHD_PKTTAG_IF(PKTTAG(p))); ++ return BCME_OK; ++} ++ ++static int ++_dhd_wlfc_pretx_pktprocess(athost_wl_status_info_t* ctx, ++ wlfc_mac_descriptor_t* entry, void* p, int header_needed, uint32* slot) ++{ ++ int rc = BCME_OK; ++ int hslot = WLFC_HANGER_MAXITEMS; ++ bool send_tim_update = FALSE; ++ uint32 htod = 0; ++ uint8 free_ctr; ++ ++ *slot = hslot; ++ ++ if (entry == NULL) { ++ entry = _dhd_wlfc_find_table_entry(ctx, p); ++ } ++ ++ if (entry == NULL) { ++ WLFC_DBGMESG(("Error: %s():%d\n", __FUNCTION__, __LINE__)); ++ return BCME_ERROR; ++ } ++ if (entry->send_tim_signal) { ++ send_tim_update = TRUE; ++ entry->send_tim_signal = 0; ++ entry->traffic_lastreported_bmp = entry->traffic_pending_bmp; ++ } ++ if (header_needed) { ++ hslot = dhd_wlfc_hanger_get_free_slot(ctx->hanger); ++ free_ctr = WLFC_SEQCOUNT(entry, DHD_PKTTAG_FIFO(PKTTAG(p))); ++ DHD_PKTTAG_SET_H2DTAG(PKTTAG(p), htod); ++ WLFC_PKTFLAG_SET_GENERATION(htod, entry->generation); ++ entry->transit_count++; ++ } ++ else { ++ hslot = WLFC_PKTID_HSLOT_GET(DHD_PKTTAG_H2DTAG(PKTTAG(p))); ++ free_ctr = WLFC_PKTID_FREERUNCTR_GET(DHD_PKTTAG_H2DTAG(PKTTAG(p))); ++ } ++ WLFC_PKTID_HSLOT_SET(htod, hslot); ++ WLFC_PKTID_FREERUNCTR_SET(htod, free_ctr); ++ DHD_PKTTAG_SETPKTDIR(PKTTAG(p), 1); ++ WL_TXSTATUS_SET_FLAGS(htod, WLFC_PKTFLAG_PKTFROMHOST); ++ WL_TXSTATUS_SET_FIFO(htod, DHD_PKTTAG_FIFO(PKTTAG(p))); ++ ++ if (!DHD_PKTTAG_CREDITCHECK(PKTTAG(p))) { ++ /* ++ Indicate that this packet is being sent in response to an ++ explicit request from the firmware side. ++ */ ++ WLFC_PKTFLAG_SET_PKTREQUESTED(htod); ++ } ++ else { ++ WLFC_PKTFLAG_CLR_PKTREQUESTED(htod); ++ } ++ if (header_needed) { ++ rc = _dhd_wlfc_pushheader(ctx, p, send_tim_update, ++ entry->traffic_lastreported_bmp, entry->mac_handle, htod); ++ if (rc == BCME_OK) { ++ DHD_PKTTAG_SET_H2DTAG(PKTTAG(p), htod); ++ /* ++ a new header was created for this packet. ++ push to hanger slot and scrub q. Since bus ++ send succeeded, increment seq number as well. ++ */ ++ rc = dhd_wlfc_hanger_pushpkt(ctx->hanger, p, hslot); ++ if (rc == BCME_OK) { ++ /* increment free running sequence count */ ++ WLFC_INCR_SEQCOUNT(entry, DHD_PKTTAG_FIFO(PKTTAG(p))); ++#ifdef PROP_TXSTATUS_DEBUG ++ ((wlfc_hanger_t*)(ctx->hanger))->items[hslot].push_time = ++ OSL_SYSUPTIME(); ++#endif ++ } ++ else { ++ WLFC_DBGMESG(("%s() hanger_pushpkt() failed, rc: %d\n", ++ __FUNCTION__, rc)); ++ } ++ } ++ } ++ else { ++ int gen; ++ ++ /* remove old header */ ++ rc = _dhd_wlfc_pullheader(ctx, p); ++ if (rc == BCME_OK) { ++ hslot = WLFC_PKTID_HSLOT_GET(DHD_PKTTAG_H2DTAG(PKTTAG(p))); ++ dhd_wlfc_hanger_get_genbit(ctx->hanger, p, hslot, &gen); ++ ++ WLFC_PKTFLAG_SET_GENERATION(htod, gen); ++ free_ctr = WLFC_PKTID_FREERUNCTR_GET(DHD_PKTTAG_H2DTAG(PKTTAG(p))); ++ /* push new header */ ++ _dhd_wlfc_pushheader(ctx, p, send_tim_update, ++ entry->traffic_lastreported_bmp, entry->mac_handle, htod); ++ } ++ } ++ *slot = hslot; ++ return rc; ++} ++ ++static int ++_dhd_wlfc_is_destination_closed(athost_wl_status_info_t* ctx, ++ wlfc_mac_descriptor_t* entry, int prec) ++{ ++ if (ctx->destination_entries.interfaces[entry->interface_id].iftype == ++ WLC_E_IF_ROLE_P2P_GO) { ++ /* - destination interface is of type p2p GO. ++ For a p2pGO interface, if the destination is OPEN but the interface is ++ CLOSEd, do not send traffic. But if the dstn is CLOSEd while there is ++ destination-specific-credit left send packets. This is because the ++ firmware storing the destination-specific-requested packet in queue. ++ */ ++ if ((entry->state == WLFC_STATE_CLOSE) && (entry->requested_credit == 0) && ++ (entry->requested_packet == 0)) ++ return 1; ++ } ++ /* AP, p2p_go -> unicast desc entry, STA/p2p_cl -> interface desc. entry */ ++ if (((entry->state == WLFC_STATE_CLOSE) && (entry->requested_credit == 0) && ++ (entry->requested_packet == 0)) || ++ (!(entry->ac_bitmap & (1 << prec)))) ++ return 1; ++ ++ return 0; ++} ++ ++static void* ++_dhd_wlfc_deque_delayedq(athost_wl_status_info_t* ctx, ++ int prec, uint8* ac_credit_spent, uint8* needs_hdr, wlfc_mac_descriptor_t** entry_out) ++{ ++ wlfc_mac_descriptor_t* entry; ++ wlfc_mac_descriptor_t* table; ++ uint8 token_pos; ++ int total_entries; ++ void* p = NULL; ++ int pout; ++ int i; ++ ++ *entry_out = NULL; ++ token_pos = ctx->token_pos[prec]; ++ /* most cases a packet will count against FIFO credit */ ++ *ac_credit_spent = 1; ++ *needs_hdr = 1; ++ ++ /* search all entries, include nodes as well as interfaces */ ++ table = (wlfc_mac_descriptor_t*)&ctx->destination_entries; ++ total_entries = sizeof(ctx->destination_entries)/sizeof(wlfc_mac_descriptor_t); ++ ++ for (i = 0; i < total_entries; i++) { ++ entry = &table[(token_pos + i) % total_entries]; ++ if (entry->occupied) { ++ if (!_dhd_wlfc_is_destination_closed(ctx, entry, prec)) { ++ p = pktq_mdeq(&entry->psq, ++ /* higher precedence will be picked up first, ++ * i.e. suppressed packets before delayed ones ++ */ ++ NBITVAL((prec << 1) + 1), &pout); ++ *needs_hdr = 0; ++ ++ if (p == NULL) { ++ if (entry->suppressed == TRUE) { ++ if ((entry->suppr_transit_count <= ++ entry->suppress_count)) { ++ entry->suppressed = FALSE; ++ } else { ++ return NULL; ++ } ++ } ++ /* De-Q from delay Q */ ++ p = pktq_mdeq(&entry->psq, ++ NBITVAL((prec << 1)), ++ &pout); ++ *needs_hdr = 1; ++ } ++ ++ if (p != NULL) { ++ /* did the packet come from suppress sub-queue? */ ++ if (entry->requested_credit > 0) { ++ entry->requested_credit--; ++#ifdef PROP_TXSTATUS_DEBUG ++ entry->dstncredit_sent_packets++; ++#endif ++ /* ++ if the packet was pulled out while destination is in ++ closed state but had a non-zero packets requested, ++ then this should not count against the FIFO credit. ++ That is due to the fact that the firmware will ++ most likely hold onto this packet until a suitable ++ time later to push it to the appropriate AC FIFO. ++ */ ++ if (entry->state == WLFC_STATE_CLOSE) ++ *ac_credit_spent = 0; ++ } ++ else if (entry->requested_packet > 0) { ++ entry->requested_packet--; ++ DHD_PKTTAG_SETONETIMEPKTRQST(PKTTAG(p)); ++ if (entry->state == WLFC_STATE_CLOSE) ++ *ac_credit_spent = 0; ++ } ++ /* move token to ensure fair round-robin */ ++ ctx->token_pos[prec] = ++ (token_pos + i + 1) % total_entries; ++ *entry_out = entry; ++ _dhd_wlfc_flow_control_check(ctx, &entry->psq, ++ DHD_PKTTAG_IF(PKTTAG(p))); ++ /* ++ A packet has been picked up, update traffic ++ availability bitmap, if applicable ++ */ ++ _dhd_wlfc_traffic_pending_check(ctx, entry, prec); ++ return p; ++ } ++ } ++ } ++ } ++ return NULL; ++} ++ ++static void* ++_dhd_wlfc_deque_sendq(athost_wl_status_info_t* ctx, int prec) ++{ ++ wlfc_mac_descriptor_t* entry; ++ void* p; ++ ++ ++ p = pktq_pdeq(&ctx->SENDQ, prec); ++ if (p != NULL) { ++ if (ETHER_ISMULTI(DHD_PKTTAG_DSTN(PKTTAG(p)))) ++ /* bc/mc packets do not have a delay queue */ ++ return p; ++ ++ entry = _dhd_wlfc_find_table_entry(ctx, p); ++ ++ if (entry == NULL) { ++ WLFC_DBGMESG(("Error: %s():%d\n", __FUNCTION__, __LINE__)); ++ return p; ++ } ++ ++ while ((p != NULL)) { ++ /* ++ - suppressed packets go to sub_queue[2*prec + 1] AND ++ - delayed packets go to sub_queue[2*prec + 0] to ensure ++ order of delivery. ++ */ ++ if (WLFC_PKTQ_PENQ(&entry->psq, (prec << 1), p) == NULL) { ++ WLFC_DBGMESG(("D")); ++ /* dhd_txcomplete(ctx->dhdp, p, FALSE); */ ++ PKTFREE(ctx->osh, p, TRUE); ++ ctx->stats.delayq_full_error++; ++ } ++ /* ++ A packet has been pushed, update traffic availability bitmap, ++ if applicable ++ */ ++ _dhd_wlfc_traffic_pending_check(ctx, entry, prec); ++ ++ p = pktq_pdeq(&ctx->SENDQ, prec); ++ if (p == NULL) ++ break; ++ ++ entry = _dhd_wlfc_find_table_entry(ctx, p); ++ ++ if ((entry == NULL) || (ETHER_ISMULTI(DHD_PKTTAG_DSTN(PKTTAG(p))))) { ++ return p; ++ } ++ } ++ } ++ return p; ++} ++ ++static int ++_dhd_wlfc_mac_entry_update(athost_wl_status_info_t* ctx, wlfc_mac_descriptor_t* entry, ++ ewlfc_mac_entry_action_t action, uint8 ifid, uint8 iftype, uint8* ea) ++{ ++ int rc = BCME_OK; ++ ++ if (action == eWLFC_MAC_ENTRY_ACTION_ADD) { ++ entry->occupied = 1; ++ entry->state = WLFC_STATE_OPEN; ++ entry->requested_credit = 0; ++ entry->interface_id = ifid; ++ entry->iftype = iftype; ++ entry->ac_bitmap = 0xff; /* update this when handling APSD */ ++ /* for an interface entry we may not care about the MAC address */ ++ if (ea != NULL) ++ memcpy(&entry->ea[0], ea, ETHER_ADDR_LEN); ++ pktq_init(&entry->psq, WLFC_PSQ_PREC_COUNT, WLFC_PSQ_LEN); ++ } ++ else if (action == eWLFC_MAC_ENTRY_ACTION_UPDATE) { ++ entry->occupied = 1; ++ entry->state = WLFC_STATE_OPEN; ++ entry->requested_credit = 0; ++ entry->interface_id = ifid; ++ entry->iftype = iftype; ++ entry->ac_bitmap = 0xff; /* update this when handling APSD */ ++ /* for an interface entry we may not care about the MAC address */ ++ if (ea != NULL) ++ memcpy(&entry->ea[0], ea, ETHER_ADDR_LEN); ++ } ++ else if (action == eWLFC_MAC_ENTRY_ACTION_DEL) { ++ entry->occupied = 0; ++ entry->state = WLFC_STATE_CLOSE; ++ entry->requested_credit = 0; ++ /* enable after packets are queued-deqeued properly. ++ pktq_flush(dhd->osh, &entry->psq, FALSE, NULL, 0); ++ */ ++ } ++ return rc; ++} ++ ++int ++_dhd_wlfc_borrow_credit(athost_wl_status_info_t* ctx, uint8 available_credit_map, int borrower_ac) ++{ ++ int lender_ac; ++ int rc = BCME_ERROR; ++ ++ if (ctx == NULL || available_credit_map == 0) { ++ WLFC_DBGMESG(("Error: %s():%d\n", __FUNCTION__, __LINE__)); ++ return BCME_BADARG; ++ } ++ ++ /* Borrow from lowest priority available AC (including BC/MC credits) */ ++ for (lender_ac = 0; lender_ac <= AC_COUNT; lender_ac++) { ++ if ((available_credit_map && (1 << lender_ac)) && ++ (ctx->FIFO_credit[lender_ac] > 0)) { ++ ctx->credits_borrowed[borrower_ac][lender_ac]++; ++ ctx->FIFO_credit[lender_ac]--; ++ rc = BCME_OK; ++ break; ++ } ++ } ++ ++ return rc; ++} ++ ++int ++dhd_wlfc_interface_entry_update(void* state, ++ ewlfc_mac_entry_action_t action, uint8 ifid, uint8 iftype, uint8* ea) ++{ ++ athost_wl_status_info_t* ctx = (athost_wl_status_info_t*)state; ++ wlfc_mac_descriptor_t* entry; ++ ++ if (ifid >= WLFC_MAX_IFNUM) ++ return BCME_BADARG; ++ ++ entry = &ctx->destination_entries.interfaces[ifid]; ++ return _dhd_wlfc_mac_entry_update(ctx, entry, action, ifid, iftype, ea); ++} ++ ++int ++dhd_wlfc_FIFOcreditmap_update(void* state, uint8* credits) ++{ ++ athost_wl_status_info_t* ctx = (athost_wl_status_info_t*)state; ++ ++ /* update the AC FIFO credit map */ ++ ctx->FIFO_credit[0] = credits[0]; ++ ctx->FIFO_credit[1] = credits[1]; ++ ctx->FIFO_credit[2] = credits[2]; ++ ctx->FIFO_credit[3] = credits[3]; ++ /* credit for bc/mc packets */ ++ ctx->FIFO_credit[4] = credits[4]; ++ /* credit for ATIM FIFO is not used yet. */ ++ ctx->FIFO_credit[5] = 0; ++ return BCME_OK; ++} ++ ++int ++dhd_wlfc_enque_sendq(void* state, int prec, void* p) ++{ ++ athost_wl_status_info_t* ctx = (athost_wl_status_info_t*)state; ++ ++ if ((state == NULL) || ++ /* prec = AC_COUNT is used for bc/mc queue */ ++ (prec > AC_COUNT) || ++ (p == NULL)) { ++ WLFC_DBGMESG(("Error: %s():%d\n", __FUNCTION__, __LINE__)); ++ return BCME_BADARG; ++ } ++ if (FALSE == dhd_prec_enq(ctx->dhdp, &ctx->SENDQ, p, prec)) { ++ ctx->stats.sendq_full_error++; ++ /* ++ WLFC_DBGMESG(("Error: %s():%d, qlen:%d\n", ++ __FUNCTION__, __LINE__, ctx->SENDQ.len)); ++ */ ++ WLFC_HOST_FIFO_DROPPEDCTR_INC(ctx, prec); ++ WLFC_DBGMESG(("Q")); ++ PKTFREE(ctx->osh, p, TRUE); ++ return BCME_ERROR; ++ } ++ ctx->stats.pktin++; ++ /* _dhd_wlfc_flow_control_check(ctx, &ctx->SENDQ, DHD_PKTTAG_IF(PKTTAG(p))); */ ++ return BCME_OK; ++} ++ ++int ++_dhd_wlfc_handle_packet_commit(athost_wl_status_info_t* ctx, int ac, ++ dhd_wlfc_commit_info_t *commit_info, f_commitpkt_t fcommit, void* commit_ctx) ++{ ++ uint32 hslot; ++ int rc; ++ ++ /* ++ if ac_fifo_credit_spent = 0 ++ ++ This packet will not count against the FIFO credit. ++ To ensure the txstatus corresponding to this packet ++ does not provide an implied credit (default behavior) ++ mark the packet accordingly. ++ ++ if ac_fifo_credit_spent = 1 ++ ++ This is a normal packet and it counts against the FIFO ++ credit count. ++ */ ++ DHD_PKTTAG_SETCREDITCHECK(PKTTAG(commit_info->p), commit_info->ac_fifo_credit_spent); ++ rc = _dhd_wlfc_pretx_pktprocess(ctx, commit_info->mac_entry, commit_info->p, ++ commit_info->needs_hdr, &hslot); ++ ++ if (rc == BCME_OK) ++ rc = fcommit(commit_ctx, commit_info->p, TRUE); ++ else ++ ctx->stats.generic_error++; ++ ++ if (rc == BCME_OK) { ++ ctx->stats.pkt2bus++; ++ if (commit_info->ac_fifo_credit_spent) { ++ ctx->stats.sendq_pkts[ac]++; ++ WLFC_HOST_FIFO_CREDIT_INC_SENTCTRS(ctx, ac); ++ } ++ } else if (rc == BCME_NORESOURCE) ++ rc = BCME_ERROR; ++ else { ++ /* ++ bus commit has failed, rollback. ++ - remove wl-header for a delayed packet ++ - save wl-header header for suppressed packets ++ */ ++ rc = _dhd_wlfc_rollback_packet_toq(ctx, commit_info->p, ++ (commit_info->pkt_type), hslot); ++ if (rc != BCME_OK) ++ ctx->stats.rollback_failed++; ++ ++ rc = BCME_ERROR; ++ } ++ ++ return rc; ++} ++ ++int ++dhd_wlfc_commit_packets(void* state, f_commitpkt_t fcommit, void* commit_ctx) ++{ ++ int ac; ++ int credit; ++ int rc; ++ dhd_wlfc_commit_info_t commit_info; ++ athost_wl_status_info_t* ctx = (athost_wl_status_info_t*)state; ++ int credit_count = 0; ++ int bus_retry_count = 0; ++ uint8 ac_available = 0; /* Bitmask for 4 ACs + BC/MC */ ++ ++ if ((state == NULL) || ++ (fcommit == NULL)) { ++ WLFC_DBGMESG(("Error: %s():%d\n", __FUNCTION__, __LINE__)); ++ return BCME_BADARG; ++ } ++ ++ memset(&commit_info, 0, sizeof(commit_info)); ++ ++ /* ++ Commit packets for regular AC traffic. Higher priority first. ++ First, use up FIFO credits available to each AC. Based on distribution ++ and credits left, borrow from other ACs as applicable ++ ++ -NOTE: ++ If the bus between the host and firmware is overwhelmed by the ++ traffic from host, it is possible that higher priority traffic ++ starves the lower priority queue. If that occurs often, we may ++ have to employ weighted round-robin or ucode scheme to avoid ++ low priority packet starvation. ++ */ ++ ++ for (ac = AC_COUNT; ac >= 0; ac--) { ++ ++ int initial_credit_count = ctx->FIFO_credit[ac]; ++ ++ /* packets from SENDQ are fresh and they'd need header and have no MAC entry */ ++ commit_info.needs_hdr = 1; ++ commit_info.mac_entry = NULL; ++ commit_info.pkt_type = eWLFC_PKTTYPE_NEW; ++ ++ do { ++ commit_info.p = _dhd_wlfc_deque_sendq(ctx, ac); ++ if (commit_info.p == NULL) ++ break; ++ else if (ETHER_ISMULTI(DHD_PKTTAG_DSTN(PKTTAG(commit_info.p)))) { ++ ASSERT(ac == AC_COUNT); ++ ++ if (ctx->FIFO_credit[ac]) { ++ rc = _dhd_wlfc_handle_packet_commit(ctx, ac, &commit_info, ++ fcommit, commit_ctx); ++ ++ /* Bus commits may fail (e.g. flow control); abort after retries */ ++ if (rc == BCME_OK) { ++ if (commit_info.ac_fifo_credit_spent) { ++ (void) _dhd_wlfc_borrow_credit(ctx, ++ ac_available, ac); ++ credit_count--; ++ } ++ } else { ++ bus_retry_count++; ++ if (bus_retry_count >= BUS_RETRIES) { ++ DHD_ERROR((" %s: bus error\n", ++ __FUNCTION__)); ++ return rc; ++ } ++ } ++ } ++ } ++ ++ } while (commit_info.p); ++ ++ for (credit = 0; credit < ctx->FIFO_credit[ac];) { ++ commit_info.p = _dhd_wlfc_deque_delayedq(ctx, ac, ++ &(commit_info.ac_fifo_credit_spent), ++ &(commit_info.needs_hdr), ++ &(commit_info.mac_entry)); ++ ++ if (commit_info.p == NULL) ++ break; ++ ++ commit_info.pkt_type = (commit_info.needs_hdr) ? eWLFC_PKTTYPE_DELAYED : ++ eWLFC_PKTTYPE_SUPPRESSED; ++ ++ rc = _dhd_wlfc_handle_packet_commit(ctx, ac, &commit_info, ++ fcommit, commit_ctx); ++ ++ /* Bus commits may fail (e.g. flow control); abort after retries */ ++ if (rc == BCME_OK) { ++ if (commit_info.ac_fifo_credit_spent) { ++ credit++; ++ } ++ } ++ else { ++ bus_retry_count++; ++ if (bus_retry_count >= BUS_RETRIES) { ++ DHD_ERROR(("dhd_wlfc_commit_packets(): bus error\n")); ++ ctx->FIFO_credit[ac] -= credit; ++ return rc; ++ } ++ } ++ } ++ ++ ctx->FIFO_credit[ac] -= credit; ++ ++ ++ /* If no credits were used, the queue is idle and can be re-used ++ Note that resv credits cannot be borrowed ++ */ ++ if (initial_credit_count == ctx->FIFO_credit[ac]) { ++ ac_available |= (1 << ac); ++ credit_count += ctx->FIFO_credit[ac]; ++ } ++ } ++ ++ /* We borrow only for AC_BE and only if no other traffic seen for DEFER_PERIOD ++ ++ Note that (ac_available & WLFC_AC_BE_TRAFFIC_ONLY) is done to: ++ a) ignore BC/MC for deferring borrow ++ b) ignore AC_BE being available along with other ACs ++ (this should happen only for pure BC/MC traffic) ++ ++ i.e. AC_VI, AC_VO, AC_BK all MUST be available (i.e. no traffic) and ++ we do not care if AC_BE and BC/MC are available or not ++ */ ++ if ((ac_available & WLFC_AC_BE_TRAFFIC_ONLY) == WLFC_AC_BE_TRAFFIC_ONLY) { ++ ++ if (ctx->allow_credit_borrow) { ++ ac = 1; /* Set ac to AC_BE and borrow credits */ ++ } ++ else { ++ int delta; ++ int curr_t = OSL_SYSUPTIME(); ++ ++ if (curr_t > ctx->borrow_defer_timestamp) ++ delta = curr_t - ctx->borrow_defer_timestamp; ++ else ++ delta = 0xffffffff + curr_t - ctx->borrow_defer_timestamp; ++ ++ if (delta >= WLFC_BORROW_DEFER_PERIOD_MS) { ++ /* Reset borrow but defer to next iteration (defensive borrowing) */ ++ ctx->allow_credit_borrow = TRUE; ++ ctx->borrow_defer_timestamp = 0; ++ } ++ return BCME_OK; ++ } ++ } ++ else { ++ /* If we have multiple AC traffic, turn off borrowing, mark time and bail out */ ++ ctx->allow_credit_borrow = FALSE; ++ ctx->borrow_defer_timestamp = OSL_SYSUPTIME(); ++ return BCME_OK; ++ } ++ ++ /* At this point, borrow all credits only for "ac" (which should be set above to AC_BE) ++ Generically use "ac" only in case we extend to all ACs in future ++ */ ++ for (; (credit_count > 0);) { ++ ++ commit_info.p = _dhd_wlfc_deque_delayedq(ctx, ac, ++ &(commit_info.ac_fifo_credit_spent), ++ &(commit_info.needs_hdr), ++ &(commit_info.mac_entry)); ++ if (commit_info.p == NULL) ++ break; ++ ++ commit_info.pkt_type = (commit_info.needs_hdr) ? eWLFC_PKTTYPE_DELAYED : ++ eWLFC_PKTTYPE_SUPPRESSED; ++ ++ rc = _dhd_wlfc_handle_packet_commit(ctx, ac, &commit_info, ++ fcommit, commit_ctx); ++ ++ /* Bus commits may fail (e.g. flow control); abort after retries */ ++ if (rc == BCME_OK) { ++ if (commit_info.ac_fifo_credit_spent) { ++ (void) _dhd_wlfc_borrow_credit(ctx, ac_available, ac); ++ credit_count--; ++ } ++ } ++ else { ++ bus_retry_count++; ++ if (bus_retry_count >= BUS_RETRIES) { ++ DHD_ERROR(("dhd_wlfc_commit_packets(): bus error\n")); ++ return rc; ++ } ++ } ++ } ++ ++ return BCME_OK; ++} ++ ++static uint8 ++dhd_wlfc_find_mac_desc_id_from_mac(dhd_pub_t *dhdp, uint8* ea) ++{ ++ wlfc_mac_descriptor_t* table = ++ ((athost_wl_status_info_t*)dhdp->wlfc_state)->destination_entries.nodes; ++ uint8 table_index; ++ ++ if (ea != NULL) { ++ for (table_index = 0; table_index < WLFC_MAC_DESC_TABLE_SIZE; table_index++) { ++ if ((memcmp(ea, &table[table_index].ea[0], ETHER_ADDR_LEN) == 0) && ++ table[table_index].occupied) ++ return table_index; ++ } ++ } ++ return WLFC_MAC_DESC_ID_INVALID; ++} ++ ++void ++dhd_wlfc_txcomplete(dhd_pub_t *dhd, void *txp, bool success, bool wake_locked) ++{ ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ void* p; ++ int fifo_id; ++ ++ if (!wake_locked) ++ dhd_os_wlfc_block(dhd); ++ ++ if (DHD_PKTTAG_SIGNALONLY(PKTTAG(txp))) { ++#ifdef PROP_TXSTATUS_DEBUG ++ wlfc->stats.signal_only_pkts_freed++; ++#endif ++ if (success) ++ /* is this a signal-only packet? */ ++ PKTFREE(wlfc->osh, txp, TRUE); ++ if (!wake_locked) ++ dhd_os_wlfc_unblock(dhd); ++ return; ++ } ++ if (!success) { ++ WLFC_DBGMESG(("At: %s():%d, bus_complete() failure for %p, htod_tag:0x%08x\n", ++ __FUNCTION__, __LINE__, txp, DHD_PKTTAG_H2DTAG(PKTTAG(txp)))); ++ dhd_wlfc_hanger_poppkt(wlfc->hanger, WLFC_PKTID_HSLOT_GET(DHD_PKTTAG_H2DTAG ++ (PKTTAG(txp))), &p, 1); ++ ++ /* indicate failure and free the packet */ ++ dhd_txcomplete(dhd, txp, FALSE); ++ ++ /* return the credit, if necessary */ ++ if (DHD_PKTTAG_CREDITCHECK(PKTTAG(txp))) { ++ int lender, credit_returned = 0; /* Note that borrower is fifo_id */ ++ ++ fifo_id = DHD_PKTTAG_FIFO(PKTTAG(txp)); ++ ++ /* Return credits to highest priority lender first */ ++ for (lender = AC_COUNT; lender >= 0; lender--) { ++ if (wlfc->credits_borrowed[fifo_id][lender] > 0) { ++ wlfc->FIFO_credit[lender]++; ++ wlfc->credits_borrowed[fifo_id][lender]--; ++ credit_returned = 1; ++ break; ++ } ++ } ++ ++ if (!credit_returned) { ++ wlfc->FIFO_credit[fifo_id]++; ++ } ++ } ++ ++ PKTFREE(wlfc->osh, txp, TRUE); ++ } ++ if (!wake_locked) ++ dhd_os_wlfc_unblock(dhd); ++ return; ++} ++ ++static int ++dhd_wlfc_compressed_txstatus_update(dhd_pub_t *dhd, uint8* pkt_info, uint8 len) ++{ ++ uint8 status_flag; ++ uint32 status; ++ int ret; ++ int remove_from_hanger = 1; ++ void* pktbuf; ++ uint8 fifo_id; ++ uint8 count = 0; ++ uint32 status_g; ++ uint32 hslot, hcnt; ++ wlfc_mac_descriptor_t* entry = NULL; ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ ++ memcpy(&status, pkt_info, sizeof(uint32)); ++ status_flag = WL_TXSTATUS_GET_FLAGS(status); ++ status_g = status & 0xff000000; ++ hslot = (status & 0x00ffff00) >> 8; ++ hcnt = status & 0xff; ++ len = pkt_info[4]; ++ ++ wlfc->stats.txstatus_in++; ++ ++ if (status_flag == WLFC_CTL_PKTFLAG_DISCARD) { ++ wlfc->stats.pkt_freed++; ++ } ++ ++ else if (status_flag == WLFC_CTL_PKTFLAG_D11SUPPRESS) { ++ wlfc->stats.d11_suppress++; ++ remove_from_hanger = 0; ++ } ++ ++ else if (status_flag == WLFC_CTL_PKTFLAG_WLSUPPRESS) { ++ wlfc->stats.wl_suppress++; ++ remove_from_hanger = 0; ++ } ++ ++ else if (status_flag == WLFC_CTL_PKTFLAG_TOSSED_BYWLC) { ++ wlfc->stats.wlc_tossed_pkts++; ++ } ++ while (count < len) { ++ status = (status_g << 24) | (hslot << 8) | (hcnt); ++ count++; ++ hslot++; ++ hcnt++; ++ ++ ret = dhd_wlfc_hanger_poppkt(wlfc->hanger, ++ WLFC_PKTID_HSLOT_GET(status), &pktbuf, remove_from_hanger); ++ if (ret != BCME_OK) { ++ /* do something */ ++ continue; ++ } ++ ++ entry = _dhd_wlfc_find_table_entry(wlfc, pktbuf); ++ ++ if (!remove_from_hanger) { ++ /* this packet was suppressed */ ++ if (!entry->suppressed || entry->generation != WLFC_PKTID_GEN(status)) { ++ entry->suppressed = TRUE; ++ entry->suppress_count = pktq_mlen(&entry->psq, ++ NBITVAL((WL_TXSTATUS_GET_FIFO(status) << 1) + 1)); ++ entry->suppr_transit_count = entry->transit_count; ++ } ++ entry->generation = WLFC_PKTID_GEN(status); ++ } ++ ++#ifdef PROP_TXSTATUS_DEBUG ++ { ++ uint32 new_t = OSL_SYSUPTIME(); ++ uint32 old_t; ++ uint32 delta; ++ old_t = ((wlfc_hanger_t*)(wlfc->hanger))->items[ ++ WLFC_PKTID_HSLOT_GET(status)].push_time; ++ ++ ++ wlfc->stats.latency_sample_count++; ++ if (new_t > old_t) ++ delta = new_t - old_t; ++ else ++ delta = 0xffffffff + new_t - old_t; ++ wlfc->stats.total_status_latency += delta; ++ wlfc->stats.latency_most_recent = delta; ++ ++ wlfc->stats.deltas[wlfc->stats.idx_delta++] = delta; ++ if (wlfc->stats.idx_delta == sizeof(wlfc->stats.deltas)/sizeof(uint32)) ++ wlfc->stats.idx_delta = 0; ++ } ++#endif /* PROP_TXSTATUS_DEBUG */ ++ ++ fifo_id = DHD_PKTTAG_FIFO(PKTTAG(pktbuf)); ++ ++ /* pick up the implicit credit from this packet */ ++ if (DHD_PKTTAG_CREDITCHECK(PKTTAG(pktbuf))) { ++ if (wlfc->proptxstatus_mode == WLFC_FCMODE_IMPLIED_CREDIT) { ++ ++ int lender, credit_returned = 0; /* Note that borrower is fifo_id */ ++ ++ /* Return credits to highest priority lender first */ ++ for (lender = AC_COUNT; lender >= 0; lender--) { ++ if (wlfc->credits_borrowed[fifo_id][lender] > 0) { ++ wlfc->FIFO_credit[lender]++; ++ wlfc->credits_borrowed[fifo_id][lender]--; ++ credit_returned = 1; ++ break; ++ } ++ } ++ ++ if (!credit_returned) { ++ wlfc->FIFO_credit[fifo_id]++; ++ } ++ } ++ } ++ else { ++ /* ++ if this packet did not count against FIFO credit, it must have ++ taken a requested_credit from the destination entry (for pspoll etc.) ++ */ ++ if (!entry) { ++ ++ entry = _dhd_wlfc_find_table_entry(wlfc, pktbuf); ++ } ++ if (!DHD_PKTTAG_ONETIMEPKTRQST(PKTTAG(pktbuf))) ++ entry->requested_credit++; ++#ifdef PROP_TXSTATUS_DEBUG ++ entry->dstncredit_acks++; ++#endif ++ } ++ if ((status_flag == WLFC_CTL_PKTFLAG_D11SUPPRESS) || ++ (status_flag == WLFC_CTL_PKTFLAG_WLSUPPRESS)) { ++ ++ ret = _dhd_wlfc_enque_suppressed(wlfc, fifo_id, pktbuf); ++ if (ret != BCME_OK) { ++ /* delay q is full, drop this packet */ ++ dhd_wlfc_hanger_poppkt(wlfc->hanger, WLFC_PKTID_HSLOT_GET(status), ++ &pktbuf, 1); ++ ++ /* indicate failure and free the packet */ ++ dhd_txcomplete(dhd, pktbuf, FALSE); ++ entry->transit_count--; ++ /* packet is transmitted Successfully by dongle ++ * after first suppress. ++ */ ++ if (entry->suppressed) { ++ entry->suppr_transit_count--; ++ } ++ PKTFREE(wlfc->osh, pktbuf, TRUE); ++ } else { ++ /* Mark suppressed to avoid a double free during wlfc cleanup */ ++ ++ dhd_wlfc_hanger_mark_suppressed(wlfc->hanger, ++ WLFC_PKTID_HSLOT_GET(status), WLFC_PKTID_GEN(status)); ++ entry->suppress_count++; ++ } ++ } ++ else { ++ dhd_txcomplete(dhd, pktbuf, TRUE); ++ entry->transit_count--; ++ ++ /* This packet is transmitted Successfully by dongle ++ * even after first suppress. ++ */ ++ if (entry->suppressed) { ++ entry->suppr_transit_count--; ++ } ++ /* free the packet */ ++ PKTFREE(wlfc->osh, pktbuf, TRUE); ++ } ++ } ++ return BCME_OK; ++} ++ ++/* Handle discard or suppress indication */ ++static int ++dhd_wlfc_txstatus_update(dhd_pub_t *dhd, uint8* pkt_info) ++{ ++ uint8 status_flag; ++ uint32 status; ++ int ret; ++ int remove_from_hanger = 1; ++ void* pktbuf; ++ uint8 fifo_id; ++ wlfc_mac_descriptor_t* entry = NULL; ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ ++ memcpy(&status, pkt_info, sizeof(uint32)); ++ status_flag = WL_TXSTATUS_GET_FLAGS(status); ++ wlfc->stats.txstatus_in++; ++ ++ if (status_flag == WLFC_CTL_PKTFLAG_DISCARD) { ++ wlfc->stats.pkt_freed++; ++ } ++ ++ else if (status_flag == WLFC_CTL_PKTFLAG_D11SUPPRESS) { ++ wlfc->stats.d11_suppress++; ++ remove_from_hanger = 0; ++ } ++ ++ else if (status_flag == WLFC_CTL_PKTFLAG_WLSUPPRESS) { ++ wlfc->stats.wl_suppress++; ++ remove_from_hanger = 0; ++ } ++ ++ else if (status_flag == WLFC_CTL_PKTFLAG_TOSSED_BYWLC) { ++ wlfc->stats.wlc_tossed_pkts++; ++ } ++ ++ ret = dhd_wlfc_hanger_poppkt(wlfc->hanger, ++ WLFC_PKTID_HSLOT_GET(status), &pktbuf, remove_from_hanger); ++ if (ret != BCME_OK) { ++ /* do something */ ++ return ret; ++ } ++ ++ entry = _dhd_wlfc_find_table_entry(wlfc, pktbuf); ++ ++ if (!remove_from_hanger) { ++ /* this packet was suppressed */ ++ if (!entry->suppressed || entry->generation != WLFC_PKTID_GEN(status)) { ++ entry->suppressed = TRUE; ++ entry->suppress_count = pktq_mlen(&entry->psq, ++ NBITVAL((WL_TXSTATUS_GET_FIFO(status) << 1) + 1)); ++ entry->suppr_transit_count = entry->transit_count; ++ } ++ entry->generation = WLFC_PKTID_GEN(status); ++ } ++ ++#ifdef PROP_TXSTATUS_DEBUG ++ { ++ uint32 new_t = OSL_SYSUPTIME(); ++ uint32 old_t; ++ uint32 delta; ++ old_t = ((wlfc_hanger_t*)(wlfc->hanger))->items[ ++ WLFC_PKTID_HSLOT_GET(status)].push_time; ++ ++ ++ wlfc->stats.latency_sample_count++; ++ if (new_t > old_t) ++ delta = new_t - old_t; ++ else ++ delta = 0xffffffff + new_t - old_t; ++ wlfc->stats.total_status_latency += delta; ++ wlfc->stats.latency_most_recent = delta; ++ ++ wlfc->stats.deltas[wlfc->stats.idx_delta++] = delta; ++ if (wlfc->stats.idx_delta == sizeof(wlfc->stats.deltas)/sizeof(uint32)) ++ wlfc->stats.idx_delta = 0; ++ } ++#endif /* PROP_TXSTATUS_DEBUG */ ++ ++ fifo_id = DHD_PKTTAG_FIFO(PKTTAG(pktbuf)); ++ ++ /* pick up the implicit credit from this packet */ ++ if (DHD_PKTTAG_CREDITCHECK(PKTTAG(pktbuf))) { ++ if (wlfc->proptxstatus_mode == WLFC_FCMODE_IMPLIED_CREDIT) { ++ ++ int lender, credit_returned = 0; /* Note that borrower is fifo_id */ ++ ++ /* Return credits to highest priority lender first */ ++ for (lender = AC_COUNT; lender >= 0; lender--) { ++ if (wlfc->credits_borrowed[fifo_id][lender] > 0) { ++ wlfc->FIFO_credit[lender]++; ++ wlfc->credits_borrowed[fifo_id][lender]--; ++ credit_returned = 1; ++ break; ++ } ++ } ++ ++ if (!credit_returned) { ++ wlfc->FIFO_credit[fifo_id]++; ++ } ++ } ++ } ++ else { ++ /* ++ if this packet did not count against FIFO credit, it must have ++ taken a requested_credit from the destination entry (for pspoll etc.) ++ */ ++ if (!entry) { ++ ++ entry = _dhd_wlfc_find_table_entry(wlfc, pktbuf); ++ } ++ if (!DHD_PKTTAG_ONETIMEPKTRQST(PKTTAG(pktbuf))) ++ entry->requested_credit++; ++#ifdef PROP_TXSTATUS_DEBUG ++ entry->dstncredit_acks++; ++#endif ++ } ++ if ((status_flag == WLFC_CTL_PKTFLAG_D11SUPPRESS) || ++ (status_flag == WLFC_CTL_PKTFLAG_WLSUPPRESS)) { ++ ++ ret = _dhd_wlfc_enque_suppressed(wlfc, fifo_id, pktbuf); ++ if (ret != BCME_OK) { ++ /* delay q is full, drop this packet */ ++ dhd_wlfc_hanger_poppkt(wlfc->hanger, WLFC_PKTID_HSLOT_GET(status), ++ &pktbuf, 1); ++ ++ /* indicate failure and free the packet */ ++ dhd_txcomplete(dhd, pktbuf, FALSE); ++ entry->transit_count--; ++ /* This packet is transmitted Successfully by ++ * dongle even after first suppress. ++ */ ++ if (entry->suppressed) { ++ entry->suppr_transit_count--; ++ } ++ PKTFREE(wlfc->osh, pktbuf, TRUE); ++ } else { ++ /* Mark suppressed to avoid a double free during wlfc cleanup */ ++ dhd_wlfc_hanger_mark_suppressed(wlfc->hanger, ++ WLFC_PKTID_HSLOT_GET(status), WLFC_PKTID_GEN(status)); ++ entry->suppress_count++; ++ } ++ } ++ else { ++ dhd_txcomplete(dhd, pktbuf, TRUE); ++ entry->transit_count--; ++ ++ /* This packet is transmitted Successfully by dongle even after first suppress. */ ++ if (entry->suppressed) { ++ entry->suppr_transit_count--; ++ } ++ /* free the packet */ ++ PKTFREE(wlfc->osh, pktbuf, TRUE); ++ } ++ return BCME_OK; ++} ++ ++static int ++dhd_wlfc_fifocreditback_indicate(dhd_pub_t *dhd, uint8* credits) ++{ ++ int i; ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ for (i = 0; i < WLFC_CTL_VALUE_LEN_FIFO_CREDITBACK; i++) { ++#ifdef PROP_TXSTATUS_DEBUG ++ wlfc->stats.fifo_credits_back[i] += credits[i]; ++#endif ++ /* update FIFO credits */ ++ if (wlfc->proptxstatus_mode == WLFC_FCMODE_EXPLICIT_CREDIT) ++ { ++ int lender; /* Note that borrower is i */ ++ ++ /* Return credits to highest priority lender first */ ++ for (lender = AC_COUNT; (lender >= 0) && (credits[i] > 0); lender--) { ++ if (wlfc->credits_borrowed[i][lender] > 0) { ++ if (credits[i] >= wlfc->credits_borrowed[i][lender]) { ++ credits[i] -= wlfc->credits_borrowed[i][lender]; ++ wlfc->FIFO_credit[lender] += ++ wlfc->credits_borrowed[i][lender]; ++ wlfc->credits_borrowed[i][lender] = 0; ++ } ++ else { ++ wlfc->credits_borrowed[i][lender] -= credits[i]; ++ wlfc->FIFO_credit[lender] += credits[i]; ++ credits[i] = 0; ++ } ++ } ++ } ++ ++ /* If we have more credits left over, these must belong to the AC */ ++ if (credits[i] > 0) { ++ wlfc->FIFO_credit[i] += credits[i]; ++ } ++ } ++ } ++ ++ return BCME_OK; ++} ++ ++static int ++dhd_wlfc_dbg_senum_check(dhd_pub_t *dhd, uint8 *value) ++{ ++ uint32 timestamp; ++ ++ (void)dhd; ++ ++ bcopy(&value[2], ×tamp, sizeof(uint32)); ++ DHD_INFO(("RXPKT: SEQ: %d, timestamp %d\n", value[1], timestamp)); ++ return BCME_OK; ++} ++ ++ ++static int ++dhd_wlfc_rssi_indicate(dhd_pub_t *dhd, uint8* rssi) ++{ ++ (void)dhd; ++ (void)rssi; ++ return BCME_OK; ++} ++ ++static int ++dhd_wlfc_mac_table_update(dhd_pub_t *dhd, uint8* value, uint8 type) ++{ ++ int rc; ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ wlfc_mac_descriptor_t* table; ++ uint8 existing_index; ++ uint8 table_index; ++ uint8 ifid; ++ uint8* ea; ++ ++ WLFC_DBGMESG(("%s(), mac [%02x:%02x:%02x:%02x:%02x:%02x],%s,idx:%d,id:0x%02x\n", ++ __FUNCTION__, value[2], value[3], value[4], value[5], value[6], value[7], ++ ((type == WLFC_CTL_TYPE_MACDESC_ADD) ? "ADD":"DEL"), ++ WLFC_MAC_DESC_GET_LOOKUP_INDEX(value[0]), value[0])); ++ ++ table = wlfc->destination_entries.nodes; ++ table_index = WLFC_MAC_DESC_GET_LOOKUP_INDEX(value[0]); ++ ifid = value[1]; ++ ea = &value[2]; ++ ++ if (type == WLFC_CTL_TYPE_MACDESC_ADD) { ++ existing_index = dhd_wlfc_find_mac_desc_id_from_mac(dhd, &value[2]); ++ if (existing_index == WLFC_MAC_DESC_ID_INVALID) { ++ /* this MAC entry does not exist, create one */ ++ if (!table[table_index].occupied) { ++ table[table_index].mac_handle = value[0]; ++ rc = _dhd_wlfc_mac_entry_update(wlfc, &table[table_index], ++ eWLFC_MAC_ENTRY_ACTION_ADD, ifid, ++ wlfc->destination_entries.interfaces[ifid].iftype, ++ ea); ++ } ++ else { ++ /* the space should have been empty, but it's not */ ++ wlfc->stats.mac_update_failed++; ++ } ++ } ++ else { ++ /* ++ there is an existing entry, move it to new index ++ if necessary. ++ */ ++ if (existing_index != table_index) { ++ /* if we already have an entry, free the old one */ ++ table[existing_index].occupied = 0; ++ table[existing_index].state = WLFC_STATE_CLOSE; ++ table[existing_index].requested_credit = 0; ++ table[existing_index].interface_id = 0; ++ /* enable after packets are queued-deqeued properly. ++ pktq_flush(dhd->osh, &table[existing_index].psq, FALSE, NULL, 0); ++ */ ++ } ++ } ++ } ++ if (type == WLFC_CTL_TYPE_MACDESC_DEL) { ++ if (table[table_index].occupied) { ++ rc = _dhd_wlfc_mac_entry_update(wlfc, &table[table_index], ++ eWLFC_MAC_ENTRY_ACTION_DEL, ifid, ++ wlfc->destination_entries.interfaces[ifid].iftype, ++ ea); ++ } ++ else { ++ /* the space should have been occupied, but it's not */ ++ wlfc->stats.mac_update_failed++; ++ } ++ } ++ BCM_REFERENCE(rc); ++ return BCME_OK; ++} ++ ++static int ++dhd_wlfc_psmode_update(dhd_pub_t *dhd, uint8* value, uint8 type) ++{ ++ /* Handle PS on/off indication */ ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ wlfc_mac_descriptor_t* table; ++ wlfc_mac_descriptor_t* desc; ++ uint8 mac_handle = value[0]; ++ int i; ++ ++ table = wlfc->destination_entries.nodes; ++ desc = &table[WLFC_MAC_DESC_GET_LOOKUP_INDEX(mac_handle)]; ++ if (desc->occupied) { ++ /* a fresh PS mode should wipe old ps credits? */ ++ desc->requested_credit = 0; ++ if (type == WLFC_CTL_TYPE_MAC_OPEN) { ++ desc->state = WLFC_STATE_OPEN; ++ DHD_WLFC_CTRINC_MAC_OPEN(desc); ++ } ++ else { ++ desc->state = WLFC_STATE_CLOSE; ++ DHD_WLFC_CTRINC_MAC_CLOSE(desc); ++ /* ++ Indicate to firmware if there is any traffic pending. ++ */ ++ for (i = AC_BE; i < AC_COUNT; i++) { ++ _dhd_wlfc_traffic_pending_check(wlfc, desc, i); ++ } ++ } ++ } ++ else { ++ wlfc->stats.psmode_update_failed++; ++ } ++ return BCME_OK; ++} ++ ++static int ++dhd_wlfc_interface_update(dhd_pub_t *dhd, uint8* value, uint8 type) ++{ ++ /* Handle PS on/off indication */ ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ wlfc_mac_descriptor_t* table; ++ uint8 if_id = value[0]; ++ ++ if (if_id < WLFC_MAX_IFNUM) { ++ table = wlfc->destination_entries.interfaces; ++ if (table[if_id].occupied) { ++ if (type == WLFC_CTL_TYPE_INTERFACE_OPEN) { ++ table[if_id].state = WLFC_STATE_OPEN; ++ /* WLFC_DBGMESG(("INTERFACE[%d] OPEN\n", if_id)); */ ++ } ++ else { ++ table[if_id].state = WLFC_STATE_CLOSE; ++ /* WLFC_DBGMESG(("INTERFACE[%d] CLOSE\n", if_id)); */ ++ } ++ return BCME_OK; ++ } ++ } ++ wlfc->stats.interface_update_failed++; ++ ++ return BCME_OK; ++} ++ ++static int ++dhd_wlfc_credit_request(dhd_pub_t *dhd, uint8* value) ++{ ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ wlfc_mac_descriptor_t* table; ++ wlfc_mac_descriptor_t* desc; ++ uint8 mac_handle; ++ uint8 credit; ++ ++ table = wlfc->destination_entries.nodes; ++ mac_handle = value[1]; ++ credit = value[0]; ++ ++ desc = &table[WLFC_MAC_DESC_GET_LOOKUP_INDEX(mac_handle)]; ++ if (desc->occupied) { ++ desc->requested_credit = credit; ++ ++ desc->ac_bitmap = value[2]; ++ } ++ else { ++ wlfc->stats.credit_request_failed++; ++ } ++ return BCME_OK; ++} ++ ++static int ++dhd_wlfc_packet_request(dhd_pub_t *dhd, uint8* value) ++{ ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ wlfc_mac_descriptor_t* table; ++ wlfc_mac_descriptor_t* desc; ++ uint8 mac_handle; ++ uint8 packet_count; ++ ++ table = wlfc->destination_entries.nodes; ++ mac_handle = value[1]; ++ packet_count = value[0]; ++ ++ desc = &table[WLFC_MAC_DESC_GET_LOOKUP_INDEX(mac_handle)]; ++ if (desc->occupied) { ++ desc->requested_packet = packet_count; ++ ++ desc->ac_bitmap = value[2]; ++ } ++ else { ++ wlfc->stats.packet_request_failed++; ++ } ++ return BCME_OK; ++} ++ ++static void ++dhd_wlfc_reorderinfo_indicate(uint8 *val, uint8 len, uchar *info_buf, uint *info_len) ++{ ++ if (info_len) { ++ if (info_buf) { ++ bcopy(val, info_buf, len); ++ *info_len = len; ++ } ++ else ++ *info_len = 0; ++ } ++} ++ ++static int ++dhd_wlfc_parse_header_info(dhd_pub_t *dhd, void* pktbuf, int tlv_hdr_len, uchar *reorder_info_buf, ++ uint *reorder_info_len) ++{ ++ uint8 type, len; ++ uint8* value; ++ uint8* tmpbuf; ++ uint16 remainder = tlv_hdr_len; ++ uint16 processed = 0; ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ tmpbuf = (uint8*)PKTDATA(dhd->osh, pktbuf); ++ if (remainder) { ++ while ((processed < (WLFC_MAX_PENDING_DATALEN * 2)) && (remainder > 0)) { ++ type = tmpbuf[processed]; ++ if (type == WLFC_CTL_TYPE_FILLER) { ++ remainder -= 1; ++ processed += 1; ++ continue; ++ } ++ ++ len = tmpbuf[processed + 1]; ++ value = &tmpbuf[processed + 2]; ++ ++ if (remainder < (2 + len)) ++ break; ++ ++ remainder -= 2 + len; ++ processed += 2 + len; ++ if (type == WLFC_CTL_TYPE_TXSTATUS) ++ dhd_wlfc_txstatus_update(dhd, value); ++ if (type == WLFC_CTL_TYPE_COMP_TXSTATUS) ++ dhd_wlfc_compressed_txstatus_update(dhd, value, len); ++ ++ else if (type == WLFC_CTL_TYPE_HOST_REORDER_RXPKTS) ++ dhd_wlfc_reorderinfo_indicate(value, len, reorder_info_buf, ++ reorder_info_len); ++ else if (type == WLFC_CTL_TYPE_FIFO_CREDITBACK) ++ dhd_wlfc_fifocreditback_indicate(dhd, value); ++ ++ else if (type == WLFC_CTL_TYPE_RSSI) ++ dhd_wlfc_rssi_indicate(dhd, value); ++ ++ else if (type == WLFC_CTL_TYPE_MAC_REQUEST_CREDIT) ++ dhd_wlfc_credit_request(dhd, value); ++ ++ else if (type == WLFC_CTL_TYPE_MAC_REQUEST_PACKET) ++ dhd_wlfc_packet_request(dhd, value); ++ ++ else if ((type == WLFC_CTL_TYPE_MAC_OPEN) || ++ (type == WLFC_CTL_TYPE_MAC_CLOSE)) ++ dhd_wlfc_psmode_update(dhd, value, type); ++ ++ else if ((type == WLFC_CTL_TYPE_MACDESC_ADD) || ++ (type == WLFC_CTL_TYPE_MACDESC_DEL)) ++ dhd_wlfc_mac_table_update(dhd, value, type); ++ ++ else if (type == WLFC_CTL_TYPE_TRANS_ID) ++ dhd_wlfc_dbg_senum_check(dhd, value); ++ ++ else if ((type == WLFC_CTL_TYPE_INTERFACE_OPEN) || ++ (type == WLFC_CTL_TYPE_INTERFACE_CLOSE)) { ++ dhd_wlfc_interface_update(dhd, value, type); ++ } ++ } ++ if (remainder != 0) { ++ /* trouble..., something is not right */ ++ wlfc->stats.tlv_parse_failed++; ++ } ++ } ++ return BCME_OK; ++} ++ ++int ++dhd_wlfc_init(dhd_pub_t *dhd) ++{ ++ char iovbuf[12]; /* Room for "tlv" + '\0' + parameter */ ++ /* enable all signals & indicate host proptxstatus logic is active */ ++ uint32 tlv = dhd->wlfc_enabled? ++ WLFC_FLAGS_RSSI_SIGNALS | ++ WLFC_FLAGS_XONXOFF_SIGNALS | ++ WLFC_FLAGS_CREDIT_STATUS_SIGNALS | ++ WLFC_FLAGS_HOST_PROPTXSTATUS_ACTIVE | ++ WLFC_FLAGS_HOST_RXRERODER_ACTIVE : 0; ++ /* WLFC_FLAGS_HOST_PROPTXSTATUS_ACTIVE | WLFC_FLAGS_HOST_RXRERODER_ACTIVE : 0; */ ++ ++ ++ /* ++ try to enable/disable signaling by sending "tlv" iovar. if that fails, ++ fallback to no flow control? Print a message for now. ++ */ ++ ++ /* enable proptxtstatus signaling by default */ ++ bcm_mkiovar("tlv", (char *)&tlv, 4, iovbuf, sizeof(iovbuf)); ++ if (dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0) < 0) { ++ DHD_ERROR(("dhd_wlfc_init(): failed to enable/disable bdcv2 tlv signaling\n")); ++ } ++ else { ++ /* ++ Leaving the message for now, it should be removed after a while; once ++ the tlv situation is stable. ++ */ ++ DHD_ERROR(("dhd_wlfc_init(): successfully %s bdcv2 tlv signaling, %d\n", ++ dhd->wlfc_enabled?"enabled":"disabled", tlv)); ++ } ++ return BCME_OK; ++} ++ ++int ++dhd_wlfc_enable(dhd_pub_t *dhd) ++{ ++ int i; ++ athost_wl_status_info_t* wlfc; ++ ++ DHD_TRACE(("Enter %s\n", __FUNCTION__)); ++ ++ if (!dhd->wlfc_enabled || dhd->wlfc_state) ++ return BCME_OK; ++ ++ /* allocate space to track txstatus propagated from firmware */ ++ dhd->wlfc_state = MALLOC(dhd->osh, sizeof(athost_wl_status_info_t)); ++ if (dhd->wlfc_state == NULL) ++ return BCME_NOMEM; ++ ++ /* initialize state space */ ++ wlfc = (athost_wl_status_info_t*)dhd->wlfc_state; ++ memset(wlfc, 0, sizeof(athost_wl_status_info_t)); ++ ++ /* remember osh & dhdp */ ++ wlfc->osh = dhd->osh; ++ wlfc->dhdp = dhd; ++ ++ wlfc->hanger = ++ dhd_wlfc_hanger_create(dhd->osh, WLFC_HANGER_MAXITEMS); ++ if (wlfc->hanger == NULL) { ++ MFREE(dhd->osh, dhd->wlfc_state, sizeof(athost_wl_status_info_t)); ++ dhd->wlfc_state = NULL; ++ return BCME_NOMEM; ++ } ++ ++ /* initialize all interfaces to accept traffic */ ++ for (i = 0; i < WLFC_MAX_IFNUM; i++) { ++ wlfc->hostif_flow_state[i] = OFF; ++ } ++ ++ /* ++ create the SENDQ containing ++ sub-queues for all AC precedences + 1 for bc/mc traffic ++ */ ++ pktq_init(&wlfc->SENDQ, (AC_COUNT + 1), WLFC_SENDQ_LEN); ++ ++ wlfc->destination_entries.other.state = WLFC_STATE_OPEN; ++ /* bc/mc FIFO is always open [credit aside], i.e. b[5] */ ++ wlfc->destination_entries.other.ac_bitmap = 0x1f; ++ wlfc->destination_entries.other.interface_id = 0; ++ ++ wlfc->proptxstatus_mode = WLFC_FCMODE_EXPLICIT_CREDIT; ++ ++ wlfc->allow_credit_borrow = TRUE; ++ wlfc->borrow_defer_timestamp = 0; ++ ++ return BCME_OK; ++} ++ ++/* release all packet resources */ ++void ++dhd_wlfc_cleanup(dhd_pub_t *dhd) ++{ ++ int i; ++ int total_entries; ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ wlfc_mac_descriptor_t* table; ++ wlfc_hanger_t* h; ++ int prec; ++ void *pkt = NULL; ++ struct pktq *txq = NULL; ++ ++ DHD_TRACE(("Enter %s\n", __FUNCTION__)); ++ if (dhd->wlfc_state == NULL) ++ return; ++ /* flush bus->txq */ ++ txq = dhd_bus_txq(dhd->bus); ++ ++ /* any in the hanger? */ ++ h = (wlfc_hanger_t*)wlfc->hanger; ++ total_entries = sizeof(wlfc->destination_entries)/sizeof(wlfc_mac_descriptor_t); ++ /* search all entries, include nodes as well as interfaces */ ++ table = (wlfc_mac_descriptor_t*)&wlfc->destination_entries; ++ ++ for (i = 0; i < total_entries; i++) { ++ if (table[i].occupied) { ++ if (table[i].psq.len) { ++ WLFC_DBGMESG(("%s(): DELAYQ[%d].len = %d\n", ++ __FUNCTION__, i, table[i].psq.len)); ++ /* release packets held in DELAYQ */ ++ pktq_flush(wlfc->osh, &table[i].psq, TRUE, NULL, 0); ++ } ++ table[i].occupied = 0; ++ } ++ } ++ /* release packets held in SENDQ */ ++ if (wlfc->SENDQ.len) ++ pktq_flush(wlfc->osh, &wlfc->SENDQ, TRUE, NULL, 0); ++ for (prec = 0; prec < txq->num_prec; prec++) { ++ pkt = pktq_pdeq(txq, prec); ++ while (pkt) { ++ for (i = 0; i < h->max_items; i++) { ++ if (pkt == h->items[i].pkt) { ++ if (h->items[i].state == WLFC_HANGER_ITEM_STATE_INUSE) { ++ PKTFREE(wlfc->osh, h->items[i].pkt, TRUE); ++ h->items[i].state = WLFC_HANGER_ITEM_STATE_FREE; ++ h->items[i].pkt = NULL; ++ h->items[i].identifier = 0; ++ } else if (h->items[i].state == ++ WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED) { ++ /* These are already freed from the psq */ ++ h->items[i].state = WLFC_HANGER_ITEM_STATE_FREE; ++ } ++ break; ++ } ++ } ++ pkt = pktq_pdeq(txq, prec); ++ } ++ } ++ /* flush remained pkt in hanger queue, not in bus->txq */ ++ for (i = 0; i < h->max_items; i++) { ++ if (h->items[i].state == WLFC_HANGER_ITEM_STATE_INUSE) { ++ PKTFREE(wlfc->osh, h->items[i].pkt, TRUE); ++ h->items[i].state = WLFC_HANGER_ITEM_STATE_FREE; ++ } else if (h->items[i].state == WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED) { ++ /* These are freed from the psq so no need to free again */ ++ h->items[i].state = WLFC_HANGER_ITEM_STATE_FREE; ++ } ++ } ++ ++ return; ++} ++ ++void ++dhd_wlfc_deinit(dhd_pub_t *dhd) ++{ ++ /* cleanup all psq related resources */ ++ athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) ++ dhd->wlfc_state; ++ ++ DHD_TRACE(("Enter %s\n", __FUNCTION__)); ++ ++ dhd_os_wlfc_block(dhd); ++ if (dhd->wlfc_state == NULL) { ++ dhd_os_wlfc_unblock(dhd); ++ return; ++ } ++ ++#ifdef PROP_TXSTATUS_DEBUG ++ { ++ int i; ++ wlfc_hanger_t* h = (wlfc_hanger_t*)wlfc->hanger; ++ for (i = 0; i < h->max_items; i++) { ++ if (h->items[i].state != WLFC_HANGER_ITEM_STATE_FREE) { ++ WLFC_DBGMESG(("%s() pkt[%d] = 0x%p, FIFO_credit_used:%d\n", ++ __FUNCTION__, i, h->items[i].pkt, ++ DHD_PKTTAG_CREDITCHECK(PKTTAG(h->items[i].pkt)))); ++ } ++ } ++ } ++#endif ++ /* delete hanger */ ++ dhd_wlfc_hanger_delete(dhd->osh, wlfc->hanger); ++ ++ /* free top structure */ ++ MFREE(dhd->osh, dhd->wlfc_state, sizeof(athost_wl_status_info_t)); ++ dhd->wlfc_state = NULL; ++ dhd_os_wlfc_unblock(dhd); ++ ++ return; ++} ++#endif /* PROP_TXSTATUS */ ++ ++void ++dhd_prot_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf) ++{ ++ bcm_bprintf(strbuf, "Protocol CDC: reqid %d\n", dhdp->prot->reqid); ++#ifdef PROP_TXSTATUS ++ dhd_os_wlfc_block(dhdp); ++ if (dhdp->wlfc_state) ++ dhd_wlfc_dump(dhdp, strbuf); ++ dhd_os_wlfc_unblock(dhdp); ++#endif ++} ++ ++void ++dhd_prot_hdrpush(dhd_pub_t *dhd, int ifidx, void *pktbuf) ++{ ++#ifdef BDC ++ struct bdc_header *h; ++#endif /* BDC */ ++ ++ DHD_TRACE(("%s: Enter\n", __FUNCTION__)); ++ ++#ifdef BDC ++ /* Push BDC header used to convey priority for buses that don't */ ++ ++ PKTPUSH(dhd->osh, pktbuf, BDC_HEADER_LEN); ++ ++ h = (struct bdc_header *)PKTDATA(dhd->osh, pktbuf); ++ ++ h->flags = (BDC_PROTO_VER << BDC_FLAG_VER_SHIFT); ++ if (PKTSUMNEEDED(pktbuf)) ++ h->flags |= BDC_FLAG_SUM_NEEDED; ++ ++ ++ h->priority = (PKTPRIO(pktbuf) & BDC_PRIORITY_MASK); ++ h->flags2 = 0; ++ h->dataOffset = 0; ++#endif /* BDC */ ++ BDC_SET_IF_IDX(h, ifidx); ++} ++ ++int ++dhd_prot_hdrpull(dhd_pub_t *dhd, int *ifidx, void *pktbuf, uchar *reorder_buf_info, ++ uint *reorder_info_len) ++{ ++#ifdef BDC ++ struct bdc_header *h; ++#endif ++ uint8 data_offset = 0; ++ ++ DHD_TRACE(("%s: Enter\n", __FUNCTION__)); ++ ++#ifdef BDC ++ if (reorder_info_len) ++ *reorder_info_len = 0; ++ /* Pop BDC header used to convey priority for buses that don't */ ++ ++ if (PKTLEN(dhd->osh, pktbuf) < BDC_HEADER_LEN) { ++ DHD_ERROR(("%s: rx data too short (%d < %d)\n", __FUNCTION__, ++ PKTLEN(dhd->osh, pktbuf), BDC_HEADER_LEN)); ++ return BCME_ERROR; ++ } ++ ++ h = (struct bdc_header *)PKTDATA(dhd->osh, pktbuf); ++ ++#if defined(NDIS630) ++ h->dataOffset = 0; ++#endif ++ ++ if (!ifidx) { ++ /* for tx packet, skip the analysis */ ++ data_offset = h->dataOffset; ++ PKTPULL(dhd->osh, pktbuf, BDC_HEADER_LEN); ++ goto exit; ++ } ++ ++ if ((*ifidx = BDC_GET_IF_IDX(h)) >= DHD_MAX_IFS) { ++ DHD_ERROR(("%s: rx data ifnum out of range (%d)\n", ++ __FUNCTION__, *ifidx)); ++ return BCME_ERROR; ++ } ++ ++ 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)); ++ if (((h->flags & BDC_FLAG_VER_MASK) >> BDC_FLAG_VER_SHIFT) == BDC_PROTO_VER_1) ++ h->dataOffset = 0; ++ else ++ return BCME_ERROR; ++ } ++ ++ 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); ++ } ++ ++ PKTSETPRIO(pktbuf, (h->priority & BDC_PRIORITY_MASK)); ++ data_offset = h->dataOffset; ++ PKTPULL(dhd->osh, pktbuf, BDC_HEADER_LEN); ++#endif /* BDC */ ++ ++#if !defined(NDIS630) ++ if (PKTLEN(dhd->osh, pktbuf) < (uint32) (data_offset << 2)) { ++ DHD_ERROR(("%s: rx data too short (%d < %d)\n", __FUNCTION__, ++ PKTLEN(dhd->osh, pktbuf), (data_offset * 4))); ++ return BCME_ERROR; ++ } ++#endif ++#ifdef PROP_TXSTATUS ++ if (dhd->wlfc_state && ++ ((athost_wl_status_info_t*)dhd->wlfc_state)->proptxstatus_mode ++ != WLFC_FCMODE_NONE && ++ (!DHD_PKTTAG_PKTDIR(PKTTAG(pktbuf)))) { ++ /* ++ - parse txstatus only for packets that came from the firmware ++ */ ++ dhd_os_wlfc_block(dhd); ++ dhd_wlfc_parse_header_info(dhd, pktbuf, (data_offset << 2), ++ reorder_buf_info, reorder_info_len); ++ ((athost_wl_status_info_t*)dhd->wlfc_state)->stats.dhd_hdrpulls++; ++ dhd_os_wlfc_unblock(dhd); ++ } ++#endif /* PROP_TXSTATUS */ ++ ++exit: ++#if !defined(NDIS630) ++ PKTPULL(dhd->osh, pktbuf, (data_offset << 2)); ++#endif ++ return 0; ++} ++ ++#if defined(PROP_TXSTATUS) ++void ++dhd_wlfc_trigger_pktcommit(dhd_pub_t *dhd) ++{ ++ if (dhd->wlfc_state && ++ (((athost_wl_status_info_t*)dhd->wlfc_state)->proptxstatus_mode ++ != WLFC_FCMODE_NONE)) { ++ dhd_os_wlfc_block(dhd); ++ dhd_wlfc_commit_packets(dhd->wlfc_state, (f_commitpkt_t)dhd_bus_txdata, ++ (void *)dhd->bus); ++ dhd_os_wlfc_unblock(dhd); ++ } ++} ++#endif ++ ++int ++dhd_prot_attach(dhd_pub_t *dhd) ++{ ++ dhd_prot_t *cdc; ++ ++ if (!(cdc = (dhd_prot_t *)DHD_OS_PREALLOC(dhd->osh, DHD_PREALLOC_PROT, ++ sizeof(dhd_prot_t)))) { ++ DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__)); ++ goto fail; ++ } ++ memset(cdc, 0, sizeof(dhd_prot_t)); ++ ++ /* ensure that the msg buf directly follows the cdc msg struct */ ++ if ((uintptr)(&cdc->msg + 1) != (uintptr)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: ++#ifndef CONFIG_DHD_USE_STATIC_BUF ++ if (cdc != NULL) ++ MFREE(dhd->osh, cdc, sizeof(dhd_prot_t)); ++#endif /* CONFIG_DHD_USE_STATIC_BUF */ ++ return BCME_NOMEM; ++} ++ ++/* ~NOTE~ What if another thread is waiting on the semaphore? Holding it? */ ++void ++dhd_prot_detach(dhd_pub_t *dhd) ++{ ++#ifdef PROP_TXSTATUS ++ dhd_wlfc_deinit(dhd); ++#endif ++#ifndef CONFIG_DHD_USE_STATIC_BUF ++ MFREE(dhd->osh, dhd->prot, sizeof(dhd_prot_t)); ++#endif /* CONFIG_DHD_USE_STATIC_BUF */ ++ 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; + wlc_rev_info_t revinfo; +@@ -556,6 +2911,11 @@ dhd_prot_init(dhd_pub_t *dhd) + if (dhd_download_fw_on_driverload) + #endif /* defined(WL_CFG80211) */ + ret = dhd_preinit_ioctls(dhd); ++ ++#ifdef PROP_TXSTATUS ++ ret = dhd_wlfc_init(dhd); ++#endif ++ + /* Always assumes wl for now */ + dhd->iswl = TRUE; + +@@ -656,7 +3016,7 @@ dhd_process_pkt_reorder_info(dhd_pub_t * + __FUNCTION__, flow_id)); + + if (ptr == NULL) { +- DHD_REORDER(("%s: received flags to cleanup, but no flow (%d) yet\n", ++ DHD_ERROR(("%s: received flags to cleanup, but no flow (%d) yet\n", + __FUNCTION__, flow_id)); + *pkt_count = 1; + *pkt = cur_pkt; +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/dhd_cfg80211.c linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_cfg80211.c +--- linux-sunxi/drivers/net/wireless/bcmdhd/dhd_cfg80211.c 2014-01-27 01:30:30.108433411 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_cfg80211.c 2014-02-15 00:43:44.795014136 +0100 +@@ -1,7 +1,7 @@ + /* + * Linux cfg80211 driver - Dongle Host Driver (DHD) related + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -152,43 +152,6 @@ default_conf_out: + + } + +-#ifdef CONFIG_NL80211_TESTMODE +-int dhd_cfg80211_testmode_cmd(struct wiphy *wiphy, void *data, int len) +-{ +- struct sk_buff *reply; +- struct wl_priv *wl; +- dhd_pub_t *dhd; +- dhd_ioctl_t *ioc = data; +- int err = 0; +- +- WL_TRACE(("entry: cmd = %d\n", ioc->cmd)); +- wl = wiphy_priv(wiphy); +- dhd = wl->pub; +- +- DHD_OS_WAKE_LOCK(dhd); +- +- /* send to dongle only if we are not waiting for reload already */ +- if (dhd->hang_was_sent) { +- WL_ERR(("HANG was sent up earlier\n")); +- DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(dhd, DHD_EVENT_TIMEOUT_MS); +- DHD_OS_WAKE_UNLOCK(dhd); +- return OSL_ERROR(BCME_DONGLE_DOWN); +- } +- +- /* currently there is only one wiphy for ifidx 0 */ +- err = dhd_ioctl_process(dhd, 0, ioc); +- if (err) +- goto done; +- +- /* response data is in ioc->buf so return ioc here */ +- reply = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(*ioc)); +- nla_put(reply, NL80211_ATTR_TESTDATA, sizeof(*ioc), ioc); +- err = cfg80211_testmode_reply(reply); +-done: +- DHD_OS_WAKE_UNLOCK(dhd); +- return err; +-} +-#endif /* CONFIG_NL80211_TESTMODE */ + + /* TODO: clean up the BT-Coex code, it still have some legacy ioctl/iovar functions */ + #define COEX_DHCP +@@ -274,10 +237,11 @@ static bool btcoex_is_sco_active(struct + + ioc_res = dev_wlc_intvar_get_reg(dev, "btc_params", 27, ¶m27); + +- WL_TRACE(("sample[%d], btc params: 27:%x\n", i, param27)); ++ WL_TRACE(("%s, sample[%d], btc params: 27:%x\n", ++ __FUNCTION__, i, param27)); + + if (ioc_res < 0) { +- WL_ERR(("ioc read btc params error\n")); ++ WL_ERR(("%s ioc read btc params error\n", __FUNCTION__)); + break; + } + +@@ -286,13 +250,13 @@ static bool btcoex_is_sco_active(struct + } + + if (sco_id_cnt > 2) { +- WL_TRACE(("sco/esco detected, pkt id_cnt:%d samples:%d\n", +- sco_id_cnt, i)); ++ WL_TRACE(("%s, sco/esco detected, pkt id_cnt:%d samples:%d\n", ++ __FUNCTION__, sco_id_cnt, i)); + res = TRUE; + break; + } + +- OSL_SLEEP(5); ++ msleep(5); + } + + return res; +@@ -335,9 +299,9 @@ static int set_btc_esco_params(struct ne + (!dev_wlc_intvar_get_reg(dev, "btc_params", 65, &saved_reg65)) && + (!dev_wlc_intvar_get_reg(dev, "btc_params", 71, &saved_reg71))) { + saved_status = TRUE; +- WL_TRACE(("saved bt_params[50,51,64,65,71]:" ++ WL_TRACE(("%s saved bt_params[50,51,64,65,71]:" + "0x%x 0x%x 0x%x 0x%x 0x%x\n", +- saved_reg50, saved_reg51, ++ __FUNCTION__, saved_reg50, saved_reg51, + saved_reg64, saved_reg65, saved_reg71)); + } else { + WL_ERR((":%s: save btc_params failed\n", +@@ -434,7 +398,7 @@ wl_cfg80211_bt_setflag(struct net_device + static void wl_cfg80211_bt_timerfunc(ulong data) + { + struct btcoex_info *bt_local = (struct btcoex_info *)data; +- WL_TRACE(("Enter\n")); ++ WL_TRACE(("%s\n", __FUNCTION__)); + bt_local->timer_on = 0; + schedule_work(&bt_local->work); + } +@@ -455,8 +419,8 @@ static void wl_cfg80211_bt_handler(struc + /* DHCP started + * provide OPPORTUNITY window to get DHCP address + */ +- WL_TRACE(("bt_dhcp stm: started \n")); +- ++ WL_TRACE(("%s bt_dhcp stm: started \n", ++ __FUNCTION__)); + btcx_inf->bt_state = BT_DHCP_OPPR_WIN; + mod_timer(&btcx_inf->timer, + jiffies + msecs_to_jiffies(BT_DHCP_OPPR_WIN_TIME)); +@@ -465,14 +429,16 @@ static void wl_cfg80211_bt_handler(struc + + case BT_DHCP_OPPR_WIN: + if (btcx_inf->dhcp_done) { +- WL_TRACE(("DHCP Done before T1 expiration\n")); ++ WL_TRACE(("%s DHCP Done before T1 expiration\n", ++ __FUNCTION__)); + goto btc_coex_idle; + } + + /* DHCP is not over yet, start lowering BT priority + * enforce btc_params + flags if necessary + */ +- WL_TRACE(("DHCP T1:%d expired\n", BT_DHCP_OPPR_WIN_TIME)); ++ WL_TRACE(("%s DHCP T1:%d expired\n", __FUNCTION__, ++ BT_DHCP_OPPR_WIN_TIME)); + if (btcx_inf->dev) + wl_cfg80211_bt_setflag(btcx_inf->dev, TRUE); + btcx_inf->bt_state = BT_DHCP_FLAG_FORCE_TIMEOUT; +@@ -483,11 +449,13 @@ static void wl_cfg80211_bt_handler(struc + + case BT_DHCP_FLAG_FORCE_TIMEOUT: + if (btcx_inf->dhcp_done) { +- WL_TRACE(("DHCP Done before T2 expiration\n")); ++ WL_TRACE(("%s DHCP Done before T2 expiration\n", ++ __FUNCTION__)); + } else { + /* Noo dhcp during T1+T2, restore BT priority */ +- WL_TRACE(("DHCP wait interval T2:%d msec expired\n", +- BT_DHCP_FLAG_FORCE_TIME)); ++ WL_TRACE(("%s DHCP wait interval T2:%d" ++ "msec expired\n", __FUNCTION__, ++ BT_DHCP_FLAG_FORCE_TIME)); + } + + /* Restoring default bt priority */ +@@ -499,7 +467,8 @@ btc_coex_idle: + break; + + default: +- WL_ERR(("error g_status=%d !!!\n", btcx_inf->bt_state)); ++ WL_ERR(("%s error g_status=%d !!!\n", __FUNCTION__, ++ btcx_inf->bt_state)); + if (btcx_inf->dev) + wl_cfg80211_bt_setflag(btcx_inf->dev, FALSE); + btcx_inf->bt_state = BT_DHCP_IDLE; +@@ -550,6 +519,7 @@ void wl_cfg80211_btcoex_deinit(struct wl + kfree(wl->btcoex_info); + wl->btcoex_info = NULL; + } ++#endif + + int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command) + { +@@ -579,8 +549,12 @@ int wl_cfg80211_set_btcoex_dhcp(struct n + strncpy((char *)&powermode_val, command + strlen("BTCOEXMODE") +1, 1); + + if (strnicmp((char *)&powermode_val, "1", strlen("1")) == 0) { +- WL_TRACE_HW4(("DHCP session starts\n")); ++ WL_TRACE_HW4(("%s: DHCP session starts\n", __FUNCTION__)); + ++#if defined(DHCP_SCAN_SUPPRESS) ++ /* Suppress scan during the DHCP */ ++ wl_cfg80211_scan_suppress(dev, 1); ++#endif /* OEM_ANDROID */ + + #ifdef PKT_FILTER_SUPPORT + dhd->dhcp_in_progress = 1; +@@ -623,21 +597,26 @@ int wl_cfg80211_set_btcoex_dhcp(struct n + btco_inf->bt_state = BT_DHCP_START; + btco_inf->timer_on = 1; + mod_timer(&btco_inf->timer, btco_inf->timer.expires); +- WL_TRACE(("enable BT DHCP Timer\n")); ++ WL_TRACE(("%s enable BT DHCP Timer\n", ++ __FUNCTION__)); + } + #endif /* COEX_DHCP */ + } + else if (saved_status == TRUE) { +- WL_ERR(("was called w/o DHCP OFF. Continue\n")); ++ WL_ERR(("%s was called w/o DHCP OFF. Continue\n", __FUNCTION__)); + } + } + else if (strnicmp((char *)&powermode_val, "2", strlen("2")) == 0) { + + +- + #ifdef PKT_FILTER_SUPPORT + dhd->dhcp_in_progress = 0; +- WL_TRACE_HW4(("DHCP is complete \n")); ++ WL_TRACE_HW4(("%s: DHCP is complete \n", __FUNCTION__)); ++ ++#if defined(DHCP_SCAN_SUPPRESS) ++ /* Since DHCP is complete, enable the scan back */ ++ wl_cfg80211_scan_suppress(dev, 0); ++#endif /* OEM_ANDROID */ + + /* Enable packet filtering */ + if (dhd->early_suspended) { +@@ -650,14 +629,15 @@ int wl_cfg80211_set_btcoex_dhcp(struct n + + #ifdef COEX_DHCP + /* Stop any bt timer because DHCP session is done */ +- WL_TRACE(("disable BT DHCP Timer\n")); ++ WL_TRACE(("%s disable BT DHCP Timer\n", __FUNCTION__)); + if (btco_inf->timer_on) { + btco_inf->timer_on = 0; + del_timer_sync(&btco_inf->timer); + + if (btco_inf->bt_state != BT_DHCP_IDLE) { + /* need to restore original btc flags & extra btc params */ +- WL_TRACE(("bt->bt_state:%d\n", btco_inf->bt_state)); ++ WL_TRACE(("%s bt->bt_state:%d\n", ++ __FUNCTION__, btco_inf->bt_state)); + /* wake up btcoex thread to restore btlags+params */ + schedule_work(&btco_inf->work); + } +@@ -688,11 +668,11 @@ int wl_cfg80211_set_btcoex_dhcp(struct n + + } + else { +- WL_ERR(("Unkwown yet power setting, ignored\n")); ++ WL_ERR(("%s Unkwown yet power setting, ignored\n", ++ __FUNCTION__)); + } + + snprintf(command, 3, "OK"); + + return (strlen("OK")); + } +-#endif +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/dhd_cfg80211.h linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_cfg80211.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/dhd_cfg80211.h 2014-01-27 01:30:30.108433411 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_cfg80211.h 2014-02-15 00:43:44.795014136 +0100 +@@ -1,7 +1,7 @@ + /* + * Linux cfg80211 driver - Dongle Host Driver (DHD) related + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -38,15 +38,6 @@ s32 dhd_cfg80211_set_p2p_info(struct wl_ + s32 dhd_cfg80211_clean_p2p_info(struct wl_priv *wl); + s32 dhd_config_dongle(struct wl_priv *wl, bool need_lock); + +-#ifdef CONFIG_NL80211_TESTMODE +-int dhd_cfg80211_testmode_cmd(struct wiphy *wiphy, void *data, int len); +-#else +-static inline int dhd_cfg80211_testmode_cmd(struct wiphy *wiphy, void *data, int len) +-{ +- return 0; +-} +-#endif +- + int wl_cfg80211_btcoex_init(struct wl_priv *wl); + void wl_cfg80211_btcoex_deinit(struct wl_priv *wl); + +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/dhd_common.c linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_common.c +--- linux-sunxi/drivers/net/wireless/bcmdhd/dhd_common.c 2014-01-27 01:30:30.109433432 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_common.c 2014-02-15 00:43:44.796014158 +0100 +@@ -1,7 +1,7 @@ + /* + * Broadcom Dongle Host Driver (DHD), common DHD core. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -21,7 +21,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: dhd_common.c 419132 2013-08-19 21:33:05Z $ ++ * $Id: dhd_common.c 373873 2012-12-10 20:45:58Z $ + */ + #include + #include +@@ -33,10 +33,8 @@ + #include + #include + #include +-#include + + #include +-#include + + #include + #include +@@ -46,26 +44,29 @@ + #ifdef WL_CFG80211 + #include + #endif +-#ifdef PNO_SUPPORT +-#include ++#ifdef WLBTAMP ++#include ++#include + #endif + #ifdef SET_RANDOM_MAC_SOFTAP + #include + #include + #endif + +-#define htod32(i) (i) +-#define htod16(i) (i) +-#define dtoh32(i) (i) +-#define dtoh16(i) (i) +-#define htodchanspec(i) (i) +-#define dtohchanspec(i) (i) ++#define htod32(i) i ++#define htod16(i) i ++#define dtoh32(i) i ++#define dtoh16(i) i ++#define htodchanspec(i) i ++#define dtohchanspec(i) i + + #ifdef PROP_TXSTATUS + #include + #include + #endif + ++extern int wifi_pm_get_mod_type(void); ++ + #ifdef WLMEDIA_HTSF + extern void htsf_update(struct dhd_info *dhd, void *data); + #endif +@@ -112,6 +113,7 @@ void dhd_set_timer(void *bus, uint wdtic + /* IOVar table */ + enum { + IOV_VERSION = 1, ++ IOV_WLMSGLEVEL, + IOV_MSGLEVEL, + IOV_BCMERRORSTR, + IOV_BCMERROR, +@@ -123,6 +125,10 @@ enum { + IOV_LOGSTAMP, + IOV_GPIOOB, + IOV_IOCTLTIMEOUT, ++#ifdef WLBTAMP ++ IOV_HCI_CMD, /* HCI command */ ++ IOV_HCI_ACL_DATA, /* HCI data packet */ ++#endif + #if defined(DHD_DEBUG) + IOV_CONS, + IOV_DCONSOLE_POLL, +@@ -130,8 +136,7 @@ enum { + #ifdef PROP_TXSTATUS + IOV_PROPTXSTATUS_ENABLE, + IOV_PROPTXSTATUS_MODE, +- IOV_PROPTXSTATUS_OPT, +-#endif /* PROP_TXSTATUS */ ++#endif + IOV_BUS_TYPE, + #ifdef WLMEDIA_HTSF + IOV_WLPKTDLYSTAT_SZ, +@@ -143,6 +148,7 @@ enum { + + const bcm_iovar_t dhd_iovars[] = { + {"version", IOV_VERSION, 0, IOVT_BUFFER, sizeof(dhd_version) }, ++ {"wlmsglevel", IOV_WLMSGLEVEL, 0, IOVT_UINT32, 0 }, + #ifdef DHD_DEBUG + {"msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0 }, + #endif /* DHD_DEBUG */ +@@ -157,6 +163,10 @@ const bcm_iovar_t dhd_iovars[] = { + {"clearcounts", IOV_CLEARCOUNTS, 0, IOVT_VOID, 0 }, + {"gpioob", IOV_GPIOOB, 0, IOVT_UINT32, 0 }, + {"ioctl_timeout", IOV_IOCTLTIMEOUT, 0, IOVT_UINT32, 0 }, ++#ifdef WLBTAMP ++ {"HCI_cmd", IOV_HCI_CMD, 0, IOVT_BUFFER, 0}, ++ {"HCI_ACL_data", IOV_HCI_ACL_DATA, 0, IOVT_BUFFER, 0}, ++#endif + #ifdef PROP_TXSTATUS + {"proptx", IOV_PROPTXSTATUS_ENABLE, 0, IOVT_UINT32, 0 }, + /* +@@ -166,8 +176,7 @@ const bcm_iovar_t dhd_iovars[] = { + 2 - Use explicit credit + */ + {"ptxmode", IOV_PROPTXSTATUS_MODE, 0, IOVT_UINT32, 0 }, +- {"proptx_opt", IOV_PROPTXSTATUS_OPT, 0, IOVT_UINT32, 0 }, +-#endif /* PROP_TXSTATUS */ ++#endif + {"bustype", IOV_BUS_TYPE, 0, IOVT_UINT32, 0}, + #ifdef WLMEDIA_HTSF + {"pktdlystatsz", IOV_WLPKTDLYSTAT_SZ, 0, IOVT_UINT8, 0 }, +@@ -177,18 +186,53 @@ const bcm_iovar_t dhd_iovars[] = { + (WLHOST_REORDERDATA_MAXFLOWS + 1) }, + {NULL, 0, 0, 0, 0 } + }; +-#define DHD_IOVAR_BUF_SIZE 128 + + void + dhd_common_init(osl_t *osh) + { ++ int select_type = 0; ++ //aw checkout which wifi had select ++ select_type = wifi_pm_get_mod_type(); ++ + #ifdef CONFIG_BCMDHD_FW_PATH +- bcm_strncpy_s(fw_path, sizeof(fw_path), CONFIG_BCMDHD_FW_PATH, MOD_PARAM_PATHLEN-1); ++ //select bcm40181/ap6181/ap6210 ++ if (select_type == 1 || select_type == 7 || select_type == 9) { ++ bcm_strncpy_s(fw_path, sizeof(fw_path), "/lib/firmware/ap6210/fw_bcm40181a2.bin", MOD_PARAM_PATHLEN-1); ++ } ++ //select bcm40183 ++ if (select_type == 2) { ++ bcm_strncpy_s(fw_path, sizeof(fw_path), "/lib/firmware/ap6210/fw_bcm40183b2.bin", MOD_PARAM_PATHLEN-1); ++ } ++ //select ap6330 ++ if (select_type == 8) { ++ bcm_strncpy_s(fw_path, sizeof(fw_path), "/lib/firmware/ap6210/fw_bcm40183b2_ag.bin", MOD_PARAM_PATHLEN-1); ++ } ++ + #else /* CONFIG_BCMDHD_FW_PATH */ + fw_path[0] = '\0'; + #endif /* CONFIG_BCMDHD_FW_PATH */ + #ifdef CONFIG_BCMDHD_NVRAM_PATH +- bcm_strncpy_s(nv_path, sizeof(nv_path), CONFIG_BCMDHD_NVRAM_PATH, MOD_PARAM_PATHLEN-1); ++ //select bcm40181 ++ if (select_type == 1) { ++ bcm_strncpy_s(nv_path, sizeof(nv_path), "/lib/firmware/ap6210/nvram_bcm40181.txt", MOD_PARAM_PATHLEN-1); ++ } ++ //select bcm40183 ++ if (select_type == 2) { ++ bcm_strncpy_s(nv_path, sizeof(nv_path), "/lib/firmware/ap6210/nvram_bcm40183.txt", MOD_PARAM_PATHLEN-1); ++ } ++ //select ap6210 ++ if (select_type == 7) { ++ bcm_strncpy_s(nv_path, sizeof(nv_path), "/lib/firmware/ap6210/nvram_ap6210.txt", MOD_PARAM_PATHLEN-1); ++ } ++ ++ //select ap6330 ++ if (select_type == 8) { ++ bcm_strncpy_s(nv_path, sizeof(nv_path), "/lib/firmware/ap6210/nvram_ap6330.txt", MOD_PARAM_PATHLEN-1); ++ } ++ //select ap6181 ++ if (select_type == 9) { ++ bcm_strncpy_s(nv_path, sizeof(nv_path), "/lib/firmware/ap6210/nvram_ap6181.txt", MOD_PARAM_PATHLEN-1); ++ } + #else /* CONFIG_BCMDHD_NVRAM_PATH */ + nv_path[0] = '\0'; + #endif /* CONFIG_BCMDHD_NVRAM_PATH */ +@@ -197,28 +241,6 @@ dhd_common_init(osl_t *osh) + #endif + } + +-void +-dhd_common_deinit(dhd_pub_t *dhd_pub, dhd_cmn_t *sa_cmn) +-{ +- osl_t *osh; +- dhd_cmn_t *cmn; +- +- if (dhd_pub != NULL) +- cmn = dhd_pub->cmn; +- else +- cmn = sa_cmn; +- +- if (!cmn) +- return; +- +- osh = cmn->osh; +- +- if (dhd_pub != NULL) +- dhd_pub->cmn = NULL; +- +- MFREE(osh, cmn, sizeof(dhd_cmn_t)); +-} +- + static int + dhd_dump(dhd_pub_t *dhdp, char *buf, int buflen) + { +@@ -234,31 +256,31 @@ dhd_dump(dhd_pub_t *dhdp, char *buf, int + 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 %u pub.maxctl %u pub.rxsz %u\n", ++ 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 %s\n", + dhdp->iswl, dhdp->drv_version, bcm_ether_ntoa(&dhdp->mac, eabuf)); +- bcm_bprintf(strbuf, "pub.bcmerror %d tickcnt %u\n", dhdp->bcmerror, dhdp->tickcnt); ++ bcm_bprintf(strbuf, "pub.bcmerror %d tickcnt %d\n", dhdp->bcmerror, dhdp->tickcnt); + + bcm_bprintf(strbuf, "dongle stats:\n"); +- bcm_bprintf(strbuf, "tx_packets %lu tx_bytes %lu tx_errors %lu tx_dropped %lu\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 %lu rx_bytes %lu rx_errors %lu rx_dropped %lu\n", ++ 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 %lu\n", dhdp->dstats.multicast); ++ bcm_bprintf(strbuf, "multicast %ld\n", dhdp->dstats.multicast); + + bcm_bprintf(strbuf, "bus stats:\n"); +- bcm_bprintf(strbuf, "tx_packets %lu tx_multicast %lu tx_errors %lu\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 %lu tx_ctlerrs %lu\n", ++ bcm_bprintf(strbuf, "tx_ctlpkts %ld tx_ctlerrs %ld\n", + dhdp->tx_ctlpkts, dhdp->tx_ctlerrs); +- bcm_bprintf(strbuf, "rx_packets %lu rx_multicast %lu rx_errors %lu \n", ++ 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 %lu rx_ctlerrs %lu rx_dropped %lu\n", ++ bcm_bprintf(strbuf, "rx_ctlpkts %ld rx_ctlerrs %ld rx_dropped %ld\n", + dhdp->rx_ctlpkts, dhdp->rx_ctlerrs, dhdp->rx_dropped); +- bcm_bprintf(strbuf, "rx_readahead_cnt %lu tx_realloc %lu\n", ++ bcm_bprintf(strbuf, "rx_readahead_cnt %ld tx_realloc %ld\n", + dhdp->rx_readahead_cnt, dhdp->tx_realloc); + bcm_bprintf(strbuf, "\n"); + +@@ -289,27 +311,17 @@ dhd_wl_ioctl_cmd(dhd_pub_t *dhd_pub, int + int + dhd_wl_ioctl(dhd_pub_t *dhd_pub, int ifindex, wl_ioctl_t *ioc, void *buf, int len) + { +- int ret = 0; +- +- if (dhd_os_proto_block(dhd_pub)) +- { ++ int ret; + +- ret = dhd_prot_ioctl(dhd_pub, ifindex, ioc, buf, len); +- if ((ret) && (dhd_pub->up)) +- /* Send hang event only if dhd_open() was success */ +- dhd_os_check_hang(dhd_pub, ifindex, ret); +- +- if (ret == -ETIMEDOUT && !dhd_pub->up) { +- DHD_ERROR(("%s: 'resumed on timeout' error is " +- "occurred before the interface does not" +- " bring up\n", __FUNCTION__)); +- dhd_pub->busstate = DHD_BUS_DOWN; +- } ++ dhd_os_proto_block(dhd_pub); + +- dhd_os_proto_unblock(dhd_pub); ++ ret = dhd_prot_ioctl(dhd_pub, ifindex, ioc, buf, len); ++ if ((ret) && (dhd_pub->up)) ++ /* Send hang event only if dhd_open() was success */ ++ dhd_os_check_hang(dhd_pub, ifindex, ret); + ++ dhd_os_proto_unblock(dhd_pub); + +- } + return ret; + } + +@@ -335,22 +347,47 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bc + bcm_strncpy_s((char*)arg, len, dhd_version, len); + break; + ++ case IOV_GVAL(IOV_WLMSGLEVEL): ++ printk("android_msg_level=0x%x\n", android_msg_level); ++#if defined(CONFIG_WIRELESS_EXT) ++ int_val = (int32)iw_msg_level; ++ bcopy(&int_val, arg, val_size); ++ printk("iw_msg_level=0x%x\n", iw_msg_level); ++#endif ++#ifdef WL_CFG80211 ++ int_val = (int32)wl_dbg_level; ++ bcopy(&int_val, arg, val_size); ++ printk("cfg_msg_level=0x%x\n", wl_dbg_level); ++#endif ++ break; ++ ++ case IOV_SVAL(IOV_WLMSGLEVEL): ++#if defined(CONFIG_WIRELESS_EXT) ++ if (int_val & DHD_IW_VAL) { ++ iw_msg_level = (uint)(int_val & 0xFFFF); ++ printk("iw_msg_level=0x%x\n", iw_msg_level); ++ } else ++#endif ++#ifdef WL_CFG80211 ++ if (int_val & DHD_CFG_VAL) { ++ wl_cfg80211_enable_trace((u32)(int_val & 0xFFFF)); ++ } else ++#endif ++ { ++ android_msg_level = (uint)int_val; ++ printk("android_msg_level=0x%x\n", android_msg_level); ++ } ++ break; ++ + case IOV_GVAL(IOV_MSGLEVEL): + int_val = (int32)dhd_msg_level; + bcopy(&int_val, arg, val_size); + break; + + case IOV_SVAL(IOV_MSGLEVEL): +-#ifdef WL_CFG80211 +- /* Enable DHD and WL logs in oneshot */ +- if (int_val & DHD_WL_VAL2) +- wl_cfg80211_enable_trace(TRUE, int_val & (~DHD_WL_VAL2)); +- else if (int_val & DHD_WL_VAL) +- wl_cfg80211_enable_trace(FALSE, WL_DBG_DBG); +- if (!(int_val & DHD_WL_VAL2)) +-#endif /* WL_CFG80211 */ + dhd_msg_level = int_val; + break; ++ + case IOV_GVAL(IOV_BCMERRORSTR): + bcm_strncpy_s((char *)arg, len, bcmerrorstr(dhd_pub->bcmerror), BCME_STRLEN); + ((char *)arg)[BCME_STRLEN - 1] = 0x00; +@@ -439,6 +476,37 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bc + break; + } + ++#ifdef WLBTAMP ++ case IOV_SVAL(IOV_HCI_CMD): { ++ amp_hci_cmd_t *cmd = (amp_hci_cmd_t *)arg; ++ ++ /* sanity check: command preamble present */ ++ if (len < HCI_CMD_PREAMBLE_SIZE) ++ return BCME_BUFTOOSHORT; ++ ++ /* sanity check: command parameters are present */ ++ if (len < (int)(HCI_CMD_PREAMBLE_SIZE + cmd->plen)) ++ return BCME_BUFTOOSHORT; ++ ++ dhd_bta_docmd(dhd_pub, cmd, len); ++ break; ++ } ++ ++ case IOV_SVAL(IOV_HCI_ACL_DATA): { ++ amp_hci_ACL_data_t *ACL_data = (amp_hci_ACL_data_t *)arg; ++ ++ /* sanity check: HCI header present */ ++ if (len < HCI_ACL_DATA_PREAMBLE_SIZE) ++ return BCME_BUFTOOSHORT; ++ ++ /* sanity check: ACL data is present */ ++ if (len < (int)(HCI_ACL_DATA_PREAMBLE_SIZE + ACL_data->dlen)) ++ return BCME_BUFTOOSHORT; ++ ++ dhd_bta_tx_hcidata(dhd_pub, ACL_data, len); ++ break; ++ } ++#endif /* WLBTAMP */ + + #ifdef PROP_TXSTATUS + case IOV_GVAL(IOV_PROPTXSTATUS_ENABLE): +@@ -557,8 +625,7 @@ dhd_prec_enq(dhd_pub_t *dhdp, struct pkt + if (pktq_pfull(q, prec)) + eprec = prec; + else if (pktq_full(q)) { +- p = pktq_peek_tail(q, &eprec); +- ASSERT(p); ++ pktq_peek_tail(q, &eprec); + if (eprec > prec || eprec < 0) + return FALSE; + } +@@ -578,91 +645,7 @@ dhd_prec_enq(dhd_pub_t *dhdp, struct pkt + } + + /* Enqueue */ +- p = pktq_penq(q, prec, pkt); +- ASSERT(p); +- +- return TRUE; +-} +- +-/* +- * Functions to drop proper pkts from queue: +- * If one pkt in queue is non-fragmented, drop first non-fragmented pkt only +- * If all pkts in queue are all fragmented, find and drop one whole set fragmented pkts +- * If can't find pkts matching upper 2 cases, drop first pkt anyway +- */ +-bool +-dhd_prec_drop_pkts(osl_t *osh, struct pktq *pq, int prec) +-{ +- struct pktq_prec *q = NULL; +- void *p, *prev = NULL, *next = NULL, *first = NULL, *last = NULL, *prev_first = NULL; +- pkt_frag_t frag_info; +- +- ASSERT(osh && pq); +- ASSERT(prec >= 0 && prec < pq->num_prec); +- +- q = &pq->q[prec]; +- p = q->head; +- +- if (p == NULL) +- return FALSE; +- +- while (p) { +- frag_info = pkt_frag_info(osh, p); +- if (frag_info == DHD_PKT_FRAG_NONE) { +- break; +- } else if (frag_info == DHD_PKT_FRAG_FIRST) { +- if (first) { +- /* No last frag pkt, use prev as last */ +- last = prev; +- } else { +- first = p; +- prev_first = prev; +- } +- } else if (frag_info == DHD_PKT_FRAG_LAST) { +- if (first) { +- last = p; +- break; +- } +- } +- +- prev = p; +- p = PKTLINK(p); +- } +- +- if ((p == NULL) || ((frag_info != DHD_PKT_FRAG_NONE) && !(first && last))) { +- /* Not found matching pkts, use oldest */ +- prev = NULL; +- p = q->head; +- frag_info = 0; +- } +- +- if (frag_info == DHD_PKT_FRAG_NONE) { +- first = last = p; +- prev_first = prev; +- } +- +- p = first; +- while (p) { +- next = PKTLINK(p); +- q->len--; +- pq->len--; +- +- PKTSETLINK(p, NULL); +- +- PKTFREE(osh, p, TRUE); +- +- if (p == last) +- break; +- +- p = next; +- } +- +- if (prev_first == NULL) { +- if ((q->head = next) == NULL) +- q->tail = NULL; +- } else { +- PKTSETLINK(prev_first, next); +- } ++ pktq_penq(q, prec, pkt); + + return TRUE; + } +@@ -740,7 +723,7 @@ dhd_ioctl(dhd_pub_t * dhd_pub, dhd_ioctl + + case DHD_GET_VERSION: + if (buflen < sizeof(int)) +- bcmerror = BCME_BUFTOOSHORT; ++ bcmerror = -BCME_BUFTOOSHORT; + else + *(int*)buf = DHD_IOCTL_VERSION; + break; +@@ -977,7 +960,6 @@ wl_show_host_event(wl_event_msg_t *event + + case WLC_E_TRACE: { + static uint32 seqnum_prev = 0; +- static uint32 logtrace_seqnum_prev = 0; + msgtrace_hdr_t hdr; + uint32 nblost; + char *s, *p; +@@ -994,72 +976,35 @@ wl_show_host_event(wl_event_msg_t *event + break; + } + +- if (hdr.trace_type == MSGTRACE_HDR_TYPE_MSG) { +- /* There are 2 bytes available at the end of data */ +- buf[MSGTRACE_HDRLEN + ntoh16(hdr.len)] = '\0'; +- +- if (ntoh32(hdr.discarded_bytes) || ntoh32(hdr.discarded_printf)) { +- printf("\nWLC_E_TRACE: [Discarded traces in dongle -->" +- "discarded_bytes %d discarded_printf %d]\n", +- ntoh32(hdr.discarded_bytes), ntoh32(hdr.discarded_printf)); +- } ++ /* There are 2 bytes available at the end of data */ ++ buf[MSGTRACE_HDRLEN + ntoh16(hdr.len)] = '\0'; + +- nblost = ntoh32(hdr.seqnum) - seqnum_prev - 1; +- if (nblost > 0) { +- printf("\nWLC_E_TRACE: [Event lost (msg) --> seqnum %d nblost %d\n", +- ntoh32(hdr.seqnum), nblost); +- } +- seqnum_prev = ntoh32(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 (*p != '\0' && (s = strstr(p, "\n")) != NULL) { +- *s = '\0'; +- printf("%s\n", p); +- p = s+1; +- } +- if (*p) printf("%s", p); +- +- /* Reset datalen to avoid display below */ +- datalen = 0; +- +- } else if (hdr.trace_type == MSGTRACE_HDR_TYPE_LOG) { +- /* Let the standard event printing work for now */ +- uint32 timestamp, w; +- if (ntoh32(hdr.seqnum) == logtrace_seqnum_prev) { +- printf("\nWLC_E_TRACE: [Event duplicate (log) %d", +- logtrace_seqnum_prev); +- } else { +- nblost = ntoh32(hdr.seqnum) - logtrace_seqnum_prev - 1; +- if (nblost > 0) { +- printf("\nWLC_E_TRACE: [Event lost (log)" +- " --> seqnum %d nblost %d\n", +- ntoh32(hdr.seqnum), nblost); +- } +- logtrace_seqnum_prev = ntoh32(hdr.seqnum); +- +- p = (char *)&buf[MSGTRACE_HDRLEN]; +- datalen -= MSGTRACE_HDRLEN; +- w = ntoh32((uint32) *p); +- p += 4; +- datalen -= 4; +- timestamp = ntoh32((uint32) *p); +- printf("Logtrace %x timestamp %x %x", +- logtrace_seqnum_prev, timestamp, w); +- +- while (datalen > 4) { +- p += 4; +- datalen -= 4; +- /* Print each word. DO NOT ntoh it. */ +- printf(" %8.8x", *((uint32 *) p)); +- } +- printf("\n"); +- } +- datalen = 0; ++ if (ntoh32(hdr.discarded_bytes) || ntoh32(hdr.discarded_printf)) { ++ printf("\nWLC_E_TRACE: [Discarded traces in dongle -->" ++ "discarded_bytes %d discarded_printf %d]\n", ++ ntoh32(hdr.discarded_bytes), ntoh32(hdr.discarded_printf)); ++ } ++ ++ nblost = ntoh32(hdr.seqnum) - seqnum_prev - 1; ++ if (nblost > 0) { ++ printf("\nWLC_E_TRACE: [Event lost --> seqnum %d nblost %d\n", ++ ntoh32(hdr.seqnum), nblost); ++ } ++ seqnum_prev = ntoh32(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'; ++ printf("%s\n", p); ++ p = s+1; + } ++ printf("%s\n", p); + ++ /* Reset datalen to avoid display below */ ++ datalen = 0; + break; + } + +@@ -1071,7 +1016,7 @@ wl_show_host_event(wl_event_msg_t *event + case WLC_E_SERVICE_FOUND: + case WLC_E_P2PO_ADD_DEVICE: + case WLC_E_P2PO_DEL_DEVICE: +- DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf)); ++ DHD_EVENT(("MACEVENT: %s, MAC: %s\n", event_name, eabuf)); + break; + + default: +@@ -1082,7 +1027,7 @@ wl_show_host_event(wl_event_msg_t *event + } + + /* show any appended data */ +- if (DHD_BYTES_ON() && DHD_EVENT_ON() && datalen) { ++ if (datalen) { + buf = (uchar *) event_data; + DHD_EVENT((" data (%d) : ", datalen)); + for (i = 0; i < datalen; i++) +@@ -1129,10 +1074,8 @@ wl_host_event(dhd_pub_t *dhd_pub, int *i + switch (type) { + #ifdef PROP_TXSTATUS + case WLC_E_FIFO_CREDIT_MAP: +- dhd_os_wlfc_block(dhd_pub); + dhd_wlfc_event(dhd_pub->info); + dhd_wlfc_FIFOcreditmap_event(dhd_pub->info, event_data); +- dhd_os_wlfc_unblock(dhd_pub); + WLFC_DBGMESG(("WLC_E_FIFO_CREDIT_MAP:(AC0,AC1,AC2,AC3),(BC_MC),(OTHER): " + "(%d,%d,%d,%d),(%d),(%d)\n", event_data[0], event_data[1], + event_data[2], +@@ -1143,13 +1086,6 @@ wl_host_event(dhd_pub_t *dhd_pub, int *i + case WLC_E_IF: + { + dhd_if_event_t *ifevent = (dhd_if_event_t *)event_data; +- +- /* Ignore the event if NOIF is set */ +- if (ifevent->flags & WLC_E_IF_FLAGS_BSSCFG_NOIF) { +- WLFC_DBGMESG(("WLC_E_IF: NO_IF set, event Ignored\r\n")); +- return (BCME_OK); +- } +- + #ifdef PROP_TXSTATUS + { + uint8* ea = pvt_data->eth.ether_dhost; +@@ -1160,8 +1096,6 @@ wl_host_event(dhd_pub_t *dhd_pub, int *i + ((ifevent->is_AP == 0) ? "STA":"AP "), + ea[0], ea[1], ea[2], ea[3], ea[4], ea[5])); + (void)ea; +- +- dhd_os_wlfc_block(dhd_pub); + if (ifevent->action == WLC_E_IF_CHANGE) + dhd_wlfc_interface_event(dhd_pub->info, + eWLFC_MAC_ENTRY_ACTION_UPDATE, +@@ -1171,7 +1105,7 @@ wl_host_event(dhd_pub_t *dhd_pub, int *i + ((ifevent->action == WLC_E_IF_ADD) ? + eWLFC_MAC_ENTRY_ACTION_ADD : eWLFC_MAC_ENTRY_ACTION_DEL), + ifevent->ifidx, ifevent->is_AP, ea); +- dhd_os_wlfc_unblock(dhd_pub); ++ + + /* dhd already has created an interface by default, for 0 */ + if (ifevent->ifidx == 0) +@@ -1225,22 +1159,17 @@ wl_host_event(dhd_pub_t *dhd_pub, int *i + htsf_update(dhd_pub->info, event_data); + break; + #endif /* WLMEDIA_HTSF */ ++#if defined(NDIS630) ++ case WLC_E_NDIS_LINK: ++ break; ++#else /* defined(NDIS630) && defined(BCMDONGLEHOST) */ + case WLC_E_NDIS_LINK: { + uint32 temp = hton32(WLC_E_LINK); + + memcpy((void *)(&pvt_data->event.event_type), &temp, + sizeof(pvt_data->event.event_type)); + } +- case WLC_E_PFN_NET_FOUND: +- case WLC_E_PFN_NET_LOST: +- break; +- case WLC_E_PFN_BSSID_NET_FOUND: +- case WLC_E_PFN_BSSID_NET_LOST: +- case WLC_E_PFN_BEST_BATCHING: +-#ifdef PNO_SUPPORT +- dhd_pno_event_handler(dhd_pub, event, (void *)event_data); +-#endif +- break; ++#endif + /* These are what external supplicant/authenticator wants */ + /* fall through */ + case WLC_E_LINK: +@@ -1561,19 +1490,6 @@ fail: + if (buf) + MFREE(dhd->osh, buf, BUF_SIZE); + } +- +-void dhd_pktfilter_offload_delete(dhd_pub_t *dhd, int id) +-{ +- char iovbuf[32]; +- int ret; +- +- bcm_mkiovar("pkt_filter_delete", (char *)&id, 4, iovbuf, sizeof(iovbuf)); +- ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); +- if (ret < 0) { +- DHD_ERROR(("%s: Failed to delete filter ID:%d, ret=%d\n", +- __FUNCTION__, id, ret)); +- } +-} + #endif /* PKT_FILTER_SUPPORT */ + + /* ========================== */ +@@ -1634,14 +1550,14 @@ dhd_aoe_arp_clr(dhd_pub_t *dhd, int idx) + { + int ret = 0; + int iov_len = 0; +- char iovbuf[DHD_IOVAR_BUF_SIZE]; ++ char iovbuf[128]; + + if (dhd == NULL) return; + if (dhd->arp_version == 1) + idx = 0; + + iov_len = bcm_mkiovar("arp_table_clear", 0, 0, iovbuf, sizeof(iovbuf)); +- if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, iov_len, TRUE, idx)) < 0) ++ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, iov_len, TRUE, idx) < 0)) + DHD_ERROR(("%s failed code %d\n", __FUNCTION__, ret)); + } + +@@ -1650,7 +1566,7 @@ dhd_aoe_hostip_clr(dhd_pub_t *dhd, int i + { + int ret = 0; + int iov_len = 0; +- char iovbuf[DHD_IOVAR_BUF_SIZE]; ++ char iovbuf[128]; + + if (dhd == NULL) return; + if (dhd->arp_version == 1) +@@ -1665,7 +1581,7 @@ void + dhd_arp_offload_add_ip(dhd_pub_t *dhd, uint32 ipaddr, int idx) + { + int iov_len = 0; +- char iovbuf[DHD_IOVAR_BUF_SIZE]; ++ char iovbuf[32]; + int retcode; + + +@@ -1724,91 +1640,15 @@ dhd_arp_get_arp_hostip_table(dhd_pub_t * + } + #endif /* ARP_OFFLOAD_SUPPORT */ + +-/* +- * Neighbor Discovery Offload: enable NDO feature +- * Called by ipv6 event handler when interface comes up/goes down +- */ +-int +-dhd_ndo_enable(dhd_pub_t *dhd, int ndo_enable) +-{ +- char iovbuf[DHD_IOVAR_BUF_SIZE]; +- int retcode; +- +- if (dhd == NULL) +- return -1; +- +- bcm_mkiovar("ndoe", (char *)&ndo_enable, 4, iovbuf, sizeof(iovbuf)); +- retcode = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); +- if (retcode) +- DHD_ERROR(("%s: failed to enabe ndo to %d, retcode = %d\n", +- __FUNCTION__, ndo_enable, retcode)); +- else +- DHD_TRACE(("%s: successfully enabed ndo offload to %d\n", +- __FUNCTION__, ndo_enable)); +- +- return retcode; +-} +- +-/* +- * Neighbor Discover Offload: add host ipv6 ip into firmware +- * Called by ipv6 event handler when interface comes up +- */ +-int +-dhd_ndo_add_ip(dhd_pub_t *dhd, char *ipv6addr, int idx) +-{ +- int iov_len = 0; +- char iovbuf[DHD_IOVAR_BUF_SIZE]; +- int retcode; +- +- if (dhd == NULL || ipv6addr == NULL) +- return -1; +- +- iov_len = bcm_mkiovar("nd_hostip", ipv6addr, +- IPV6_ADDR_LEN, iovbuf, sizeof(iovbuf)); +- retcode = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, iov_len, TRUE, idx); +- +- if (retcode) +- DHD_ERROR(("%s: ndo ip addr add failed, retcode = %d\n", +- __FUNCTION__, retcode)); +- else +- DHD_ERROR(("%s: ndo ipaddr entry added \n", +- __FUNCTION__)); +- return retcode; +-} +- +-/* +- * Neighbor Discover Offload: disable NDO feature +- * Called by ipv6 event handler when interface goes down +- */ +-int +-dhd_ndo_remove_ip(dhd_pub_t *dhd, int idx) +-{ +- int iov_len = 0; +- char iovbuf[DHD_IOVAR_BUF_SIZE]; +- int retcode; +- +- if (dhd == NULL) +- return -1; +- +- iov_len = bcm_mkiovar("nd_hostip_clear", (char *)NULL, +- 0, iovbuf, sizeof(iovbuf)); +- retcode = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, iov_len, TRUE, idx); +- +- if (retcode) +- DHD_ERROR(("%s: ndo ip addr remove failed, retcode = %d\n", +- __FUNCTION__, retcode)); +- else +- DHD_TRACE(("%s: ndo ipaddr entry removed \n", +- __FUNCTION__)); +- +- return retcode; +-} +- + /* send up locally generated event */ + void + dhd_sendup_event_common(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data) + { + switch (ntoh32(event->event_type)) { ++#ifdef WLBTAMP ++ case WLC_E_BTA_HCI_EVENT: ++ break; ++#endif /* WLBTAMP */ + default: + break; + } +@@ -1861,68 +1701,48 @@ bool dhd_is_associated(dhd_pub_t *dhd, v + int + dhd_get_suspend_bcn_li_dtim(dhd_pub_t *dhd) + { +- int bcn_li_dtim = 1; /* deafult no dtim skip setting */ ++ int bcn_li_dtim; + int ret = -1; +- int dtim_period = 0; +- int ap_beacon = 0; +- int allowed_skip_dtim_cnt = 0; ++ int dtim_assoc = 0; ++ ++ bcn_li_dtim = dhd->suspend_bcn_li_dtim; ++ + /* Check if associated */ + if (dhd_is_associated(dhd, NULL, NULL) == FALSE) { + DHD_TRACE(("%s NOT assoc ret %d\n", __FUNCTION__, ret)); + goto exit; + } + +- /* read associated AP beacon interval */ +- if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_BCNPRD, +- &ap_beacon, sizeof(ap_beacon), FALSE, 0)) < 0) { +- DHD_ERROR(("%s get beacon failed code %d\n", __FUNCTION__, ret)); +- goto exit; +- } +- +- /* if associated APs Beacon more that 100msec do no dtim skip */ +- if (ap_beacon > MAX_DTIM_SKIP_BEACON_INTERVAL) { +- DHD_ERROR(("%s NO dtim skip for AP with beacon %d ms\n", __FUNCTION__, ap_beacon)); +- goto exit; +- } +- +- /* read associated ap's dtim setup */ ++ /* if assoc grab ap's dtim value */ + if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_DTIMPRD, +- &dtim_period, sizeof(dtim_period), FALSE, 0)) < 0) { ++ &dtim_assoc, sizeof(dtim_assoc), FALSE, 0)) < 0) { + DHD_ERROR(("%s failed code %d\n", __FUNCTION__, ret)); + goto exit; + } + ++ DHD_ERROR(("%s bcn_li_dtim=%d DTIM=%d Listen=%d\n", ++ __FUNCTION__, bcn_li_dtim, dtim_assoc, LISTEN_INTERVAL)); ++ + /* if not assocated just eixt */ +- if (dtim_period == 0) { ++ if (dtim_assoc == 0) { + goto exit; + } + +- /* attemp to use platform defined dtim skip interval */ +- bcn_li_dtim = dhd->suspend_bcn_li_dtim; +- + /* check if sta listen interval fits into AP dtim */ +- if (dtim_period > CUSTOM_LISTEN_INTERVAL) { ++ if (dtim_assoc > LISTEN_INTERVAL) { + /* AP DTIM to big for our Listen Interval : no dtim skiping */ +- bcn_li_dtim = NO_DTIM_SKIP; ++ bcn_li_dtim = 1; + DHD_ERROR(("%s DTIM=%d > Listen=%d : too big ...\n", +- __FUNCTION__, dtim_period, CUSTOM_LISTEN_INTERVAL)); ++ __FUNCTION__, dtim_assoc, LISTEN_INTERVAL)); + goto exit; + } + +- if ((dtim_period * ap_beacon * bcn_li_dtim) > MAX_DTIM_ALLOWED_INTERVAL) { +- allowed_skip_dtim_cnt = MAX_DTIM_ALLOWED_INTERVAL / (dtim_period * ap_beacon); +- bcn_li_dtim = (allowed_skip_dtim_cnt != 0) ? allowed_skip_dtim_cnt : NO_DTIM_SKIP; +- } +- +- if ((bcn_li_dtim * dtim_period) > CUSTOM_LISTEN_INTERVAL) { ++ if ((bcn_li_dtim * dtim_assoc) > LISTEN_INTERVAL) { + /* Round up dtim_skip to fit into STAs Listen Interval */ +- bcn_li_dtim = (int)(CUSTOM_LISTEN_INTERVAL / dtim_period); ++ bcn_li_dtim = (int)(LISTEN_INTERVAL / dtim_assoc); + DHD_TRACE(("%s agjust dtim_skip as %d\n", __FUNCTION__, bcn_li_dtim)); + } + +- DHD_ERROR(("%s beacon=%d bcn_li_dtim=%d DTIM=%d Listen=%d\n", +- __FUNCTION__, ap_beacon, bcn_li_dtim, dtim_period, CUSTOM_LISTEN_INTERVAL)); +- + exit: + return bcn_li_dtim; + } +@@ -1939,12 +1759,213 @@ bool dhd_support_sta_mode(dhd_pub_t *dhd + return TRUE; + } + ++#if defined(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)); ++ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) >= 0) { ++ /* clear pfn */ ++ iov_len = bcm_mkiovar("pfnclear", 0, 0, iovbuf, sizeof(iovbuf)); ++ if (iov_len) { ++ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, ++ iov_len, TRUE, 0)) < 0) { ++ DHD_ERROR(("%s failed code %d\n", __FUNCTION__, ret)); ++ } ++ } ++ else { ++ ret = -1; ++ DHD_ERROR(("%s failed code %d\n", __FUNCTION__, iov_len)); ++ } ++ } ++ else ++ DHD_ERROR(("%s failed code %d\n", __FUNCTION__, 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", __FUNCTION__)); ++ return ret; ++ } ++ ++#ifndef WL_SCHED_SCAN ++ if (!dhd_support_sta_mode(dhd)) ++ return (ret); ++ ++ memset(iovbuf, 0, sizeof(iovbuf)); ++ ++ if ((pfn_enabled) && (dhd_is_associated(dhd, NULL, NULL) == TRUE)) { ++ DHD_ERROR(("%s pno is NOT enable : called in assoc mode , ignore\n", __FUNCTION__)); ++ return ret; ++ } ++#endif /* !WL_SCHED_SCAN */ ++ ++ /* Enable/disable PNO */ ++ if ((ret = bcm_mkiovar("pfn", (char *)&pfn_enabled, 4, iovbuf, sizeof(iovbuf))) > 0) { ++ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, ++ iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) { ++ DHD_ERROR(("%s failed for error=%d\n", __FUNCTION__, ret)); ++ return ret; ++ } ++ else { ++ dhd->pno_enable = pfn_enabled; ++ DHD_TRACE(("%s set pno as %s\n", ++ __FUNCTION__, dhd->pno_enable ? "Enable" : "Disable")); ++ } ++ } ++ else DHD_ERROR(("%s failed err=%d\n", __FUNCTION__, ret)); ++ ++ return ret; ++} ++ ++/* Function to execute combined scan */ ++int ++dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr, ++ int pno_repeat, int pno_freq_expo_max) ++{ ++ int err = -1; ++ char iovbuf[128]; ++ int k, i; ++ wl_pfn_param_t pfn_param; ++ wl_pfn_t pfn_element; ++ uint len = 0; ++ ++ DHD_TRACE(("%s nssid=%d nchan=%d\n", __FUNCTION__, nssid, scan_fr)); ++ ++ if ((!dhd) || (!ssids_local)) { ++ DHD_ERROR(("%s error exit(%s %s)\n", __FUNCTION__, ++ (!dhd)?"dhd is null":"", (!ssids_local)?"ssid is null":"")); ++ err = -1; ++ return err; ++ } ++#ifndef WL_SCHED_SCAN ++ if (!dhd_support_sta_mode(dhd)) ++ return err; ++#endif /* !WL_SCHED_SCAN */ ++ ++ /* 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 */ ++ if ((err = dhd_pno_clean(dhd)) < 0) { ++ DHD_ERROR(("%s failed error=%d\n", __FUNCTION__, err)); ++ return err; ++ } ++ memset(iovbuf, 0, sizeof(iovbuf)); ++ memset(&pfn_param, 0, sizeof(pfn_param)); ++ memset(&pfn_element, 0, sizeof(pfn_element)); ++ ++ /* set pfn parameters */ ++ pfn_param.version = htod32(PFN_VERSION); ++ pfn_param.flags = htod16((PFN_LIST_ORDER << SORT_CRITERIA_BIT)); ++ ++ /* check and set extra pno params */ ++ if ((pno_repeat != 0) || (pno_freq_expo_max != 0)) { ++ pfn_param.flags |= htod16(ENABLE << ENABLE_ADAPTSCAN_BIT); ++ pfn_param.repeat = (uchar) (pno_repeat); ++ pfn_param.exp = (uchar) (pno_freq_expo_max); ++ } ++ /* set up pno scan fr */ ++ if (scan_fr != 0) ++ pfn_param.scan_freq = htod32(scan_fr); ++ ++ if (pfn_param.scan_freq > PNO_SCAN_MAX_FW_SEC) { ++ DHD_ERROR(("%s pno freq above %d sec\n", __FUNCTION__, PNO_SCAN_MAX_FW_SEC)); ++ return err; ++ } ++ if (pfn_param.scan_freq < PNO_SCAN_MIN_FW_SEC) { ++ DHD_ERROR(("%s pno freq less %d sec\n", __FUNCTION__, PNO_SCAN_MIN_FW_SEC)); ++ return err; ++ } ++ ++ len = bcm_mkiovar("pfn_set", (char *)&pfn_param, sizeof(pfn_param), iovbuf, sizeof(iovbuf)); ++ if ((err = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, len, TRUE, 0)) < 0) { ++ DHD_ERROR(("%s pfn_set failed for error=%d\n", ++ __FUNCTION__, err)); ++ return err; ++ } ++ ++ /* set all pfn ssid */ ++ for (i = 0; i < nssid; i++) { ++ ++ pfn_element.infra = htod32(DOT11_BSSTYPE_INFRASTRUCTURE); ++ pfn_element.auth = (DOT11_OPEN_SYSTEM); ++ pfn_element.wpa_auth = htod32(WPA_AUTH_PFN_ANY); ++ pfn_element.wsec = htod32(0); ++ pfn_element.infra = htod32(1); ++ pfn_element.flags = htod32(ENABLE << WL_PFN_HIDDEN_BIT); ++ 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; ++ ++ if ((len = ++ bcm_mkiovar("pfn_add", (char *)&pfn_element, ++ sizeof(pfn_element), iovbuf, sizeof(iovbuf))) > 0) { ++ if ((err = ++ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, len, TRUE, 0)) < 0) { ++ DHD_ERROR(("%s failed for i=%d error=%d\n", ++ __FUNCTION__, i, err)); ++ return err; ++ } ++ else ++ DHD_TRACE(("%s set OK with PNO time=%d repeat=%d max_adjust=%d\n", ++ __FUNCTION__, pfn_param.scan_freq, ++ pfn_param.repeat, pfn_param.exp)); ++ } ++ else DHD_ERROR(("%s failed err=%d\n", __FUNCTION__, 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 /* OEM_ANDROID && PNO_SUPPORT */ ++ + #if defined(KEEP_ALIVE) + int dhd_keep_alive_onoff(dhd_pub_t *dhd) + { + char buf[256]; + const char *str; +- wl_mkeep_alive_pkt_t mkeep_alive_pkt = {0}; ++ wl_mkeep_alive_pkt_t mkeep_alive_pkt; + wl_mkeep_alive_pkt_t *mkeep_alive_pktp; + int buf_len; + int str_len; +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c +--- linux-sunxi/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c 2014-02-15 00:43:44.795014136 +0100 +@@ -1,6 +1,6 @@ + /* + * Customer code to add GPIO control during WLAN start/stop +-* Copyright (C) 1999-2013, Broadcom Corporation ++* Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -20,7 +20,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +-* $Id: dhd_custom_gpio.c 417465 2013-08-09 11:47:27Z $ ++* $Id: dhd_custom_gpio.c 353167 2012-08-24 22:11:30Z $ + */ + + #include +@@ -34,16 +34,24 @@ + #include + #include + ++#include ++#include ++ + #define WL_ERROR(x) printf x +-#define WL_TRACE(x) ++#define WL_TRACE(x) printf x ++ ++extern void sunximmc_rescan_card(unsigned id, unsigned insert); ++extern void wifi_pm_power(int on); + + #ifdef CUSTOMER_HW ++#include ++#if defined(CUSTOMER_OOB) ++extern int bcm_wlan_get_oob_irq(void); ++#endif + extern void bcm_wlan_power_off(int); + extern void bcm_wlan_power_on(int); + #endif /* CUSTOMER_HW */ + #if defined(CUSTOMER_HW2) +- +- + #ifdef CONFIG_WIFI_CONTROL_FUNC + int wifi_set_power(int on, unsigned long msec); + int wifi_get_irq_number(unsigned long *irq_flags_ptr); +@@ -63,12 +71,12 @@ void *wifi_get_country_code(char *ccode) + extern int sdioh_mmc_irq(int irq); + #endif /* (BCMLXSDMMC) */ + +-#if defined(CUSTOMER_HW3) ++#ifdef CUSTOMER_HW3 + #include + #endif + + /* Customer specific Host GPIO defintion */ +-static int dhd_oob_gpio_num = -1; ++static int dhd_oob_gpio_num = 2; + + module_param(dhd_oob_gpio_num, int, 0644); + MODULE_PARM_DESC(dhd_oob_gpio_num, "DHD oob gpio number"); +@@ -86,11 +94,14 @@ MODULE_PARM_DESC(dhd_oob_gpio_num, "DHD + */ + int dhd_customer_oob_irq_map(unsigned long *irq_flags_ptr) + { +- int host_oob_irq = 0; ++ int host_oob_irq = -1; + + #if defined(CUSTOMER_HW2) + host_oob_irq = wifi_get_irq_number(irq_flags_ptr); + ++#elif defined(CUSTOMER_OOB) ++ host_oob_irq = bcm_wlan_get_oob_irq(); ++ pr_info("bcmdhd: irq=%d, flags=0x%08lx\n", host_oob_irq, *irq_flags_ptr); + #else + #if defined(CUSTOM_OOB_GPIO_NUM) + if (dhd_oob_gpio_num < 0) { +@@ -108,7 +119,7 @@ int dhd_customer_oob_irq_map(unsigned lo + __FUNCTION__, dhd_oob_gpio_num)); + + #if defined CUSTOMER_HW +- host_oob_irq = MSM_GPIO_TO_INT(dhd_oob_gpio_num); ++ pr_err("%s: should not be here!\n", __FUNCTION__); + #elif defined CUSTOMER_HW3 + gpio_request(dhd_oob_gpio_num, "oob irq"); + host_oob_irq = gpio_to_irq(dhd_oob_gpio_num); +@@ -124,16 +135,19 @@ int dhd_customer_oob_irq_map(unsigned lo + void + dhd_customer_gpio_wlan_ctrl(int onoff) + { ++ static int sdc_id = 3; ++ + switch (onoff) { + case WLAN_RESET_OFF: + WL_TRACE(("%s: call customer specific GPIO to insert WLAN RESET\n", + __FUNCTION__)); + #ifdef CUSTOMER_HW +- bcm_wlan_power_off(2); ++ wifi_pm_power(0); + #endif /* CUSTOMER_HW */ + #if defined(CUSTOMER_HW2) +- wifi_set_power(0, WIFI_TURNOFF_DELAY); ++ wifi_set_power(0, 0); + #endif ++ mdelay(100); + WL_ERROR(("=========== WLAN placed in RESET ========\n")); + break; + +@@ -141,11 +155,12 @@ dhd_customer_gpio_wlan_ctrl(int onoff) + WL_TRACE(("%s: callc customer specific GPIO to remove WLAN RESET\n", + __FUNCTION__)); + #ifdef CUSTOMER_HW +- bcm_wlan_power_on(2); ++ wifi_pm_power(1); + #endif /* CUSTOMER_HW */ + #if defined(CUSTOMER_HW2) + wifi_set_power(1, 0); + #endif ++ mdelay(100); + WL_ERROR(("=========== WLAN going back to live ========\n")); + break; + +@@ -153,18 +168,22 @@ dhd_customer_gpio_wlan_ctrl(int onoff) + WL_TRACE(("%s: call customer specific GPIO to turn off WL_REG_ON\n", + __FUNCTION__)); + #ifdef CUSTOMER_HW +- bcm_wlan_power_off(1); ++ wifi_pm_power(0); ++ sunximmc_rescan_card(sdc_id, 0); + #endif /* CUSTOMER_HW */ ++ WL_ERROR(("=========== WLAN placed in POWER OFF ========\n")); + break; + + case WLAN_POWER_ON: + WL_TRACE(("%s: call customer specific GPIO to turn on WL_REG_ON\n", + __FUNCTION__)); + #ifdef CUSTOMER_HW +- bcm_wlan_power_on(1); ++ wifi_pm_power(1); ++ sunximmc_rescan_card(sdc_id, 1); + /* Lets customer power to get stable */ +- OSL_DELAY(200); + #endif /* CUSTOMER_HW */ ++ mdelay(100); ++ WL_ERROR(("=========== WLAN placed in POWER ON ========\n")); + break; + } + } +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/dhd_dbg.h linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_dbg.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/dhd_dbg.h 2014-01-27 01:30:30.108433411 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_dbg.h 2014-02-15 00:43:44.795014136 +0100 +@@ -1,7 +1,7 @@ + /* + * Debug/trace/assert driver definitions for Dongle Host Driver. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -21,7 +21,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: dhd_dbg.h 419132 2013-08-19 21:33:05Z $ ++ * $Id: dhd_dbg.h 353490 2012-08-27 21:10:02Z $ + */ + + #ifndef _dhd_dbg_ +@@ -47,7 +47,6 @@ + #define DHD_ISCAN(args) do {if (dhd_msg_level & DHD_ISCAN_VAL) printf args;} while (0) + #define DHD_ARPOE(args) do {if (dhd_msg_level & DHD_ARPOE_VAL) printf args;} while (0) + #define DHD_REORDER(args) do {if (dhd_msg_level & DHD_REORDER_VAL) printf args;} while (0) +-#define DHD_PNO(args) do {if (dhd_msg_level & DHD_PNO_VAL) printf args;} while (0) + + #define DHD_TRACE_HW4 DHD_TRACE + +@@ -66,8 +65,6 @@ + #define DHD_ISCAN_ON() (dhd_msg_level & DHD_ISCAN_VAL) + #define DHD_ARPOE_ON() (dhd_msg_level & DHD_ARPOE_VAL) + #define DHD_REORDER_ON() (dhd_msg_level & DHD_REORDER_VAL) +-#define DHD_NOCHECKDIED_ON() (dhd_msg_level & DHD_NOCHECKDIED_VAL) +-#define DHD_PNO_ON() (dhd_msg_level & DHD_PNO_VAL) + + #else /* defined(BCMDBG) || defined(DHD_DEBUG) */ + +@@ -86,7 +83,6 @@ + #define DHD_ISCAN(args) + #define DHD_ARPOE(args) + #define DHD_REORDER(args) +-#define DHD_PNO(args) + + #define DHD_TRACE_HW4 DHD_TRACE + +@@ -105,9 +101,6 @@ + #define DHD_ISCAN_ON() 0 + #define DHD_ARPOE_ON() 0 + #define DHD_REORDER_ON() 0 +-#define DHD_NOCHECKDIED_ON() 0 +-#define DHD_PNO_ON() 0 +- + #endif + + #define DHD_LOG(args) +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/dhd_gpio.c linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_gpio.c +--- linux-sunxi/drivers/net/wireless/bcmdhd/dhd_gpio.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_gpio.c 2014-02-15 00:43:44.795014136 +0100 +@@ -0,0 +1,47 @@ ++/* ++* Customer code to add GPIO control during WLAN start/stop ++* Copyright (C) 1999-2011, Broadcom Corporation ++* ++* Unless you and Broadcom execute a separate written software license ++* agreement governing use of this software, this software is licensed to you ++* under the terms of the GNU General Public License version 2 (the "GPL"), ++* available at http://www.broadcom.com/licenses/GPLv2.php, with the ++* following added to such license: ++* ++* As a special exception, the copyright holders of this software give you ++* permission to link this software with independent modules, and to copy and ++* distribute the resulting executable under terms of your choice, provided that ++* you also meet, for each linked independent module, the terms and conditions of ++* the license of that module. An independent module is a module which is not ++* derived from this software. The special exception does not apply to any ++* modifications of the software. ++* ++* Notwithstanding the above, under no circumstances may you combine this ++* software in any way with any other Broadcom software provided under a license ++* other than the GPL, without Broadcom's express prior written consent. ++* ++* $Id: dhd_custom_gpio.c,v 1.2.42.1 2010-10-19 00:41:09 Exp $ ++*/ ++ ++#include ++ ++#include ++#include ++ ++#ifdef CUSTOMER_HW ++ ++extern int __gpio_to_irq(unsigned gpio); ++extern int gpio_direction_input(unsigned gpio); ++extern int gpio_request(unsigned gpio, const char *label); ++extern void gpio_free(unsigned gpio); ++ ++#ifdef CUSTOMER_OOB ++extern int wl_host_wake_irqno; ++int bcm_wlan_get_oob_irq(void) ++{ ++ return wl_host_wake_irqno; ++} ++#endif ++ ++ ++#endif /* CUSTOMER_HW */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/dhd.h linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/dhd.h 2014-01-27 01:30:30.108433411 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd.h 2014-02-15 00:43:44.795014136 +0100 +@@ -4,7 +4,7 @@ + * Provides type definitions and function prototypes used to link the + * DHD OS, bus, and protocol modules. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -24,7 +24,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: dhd.h 419132 2013-08-19 21:33:05Z $ ++ * $Id: dhd.h 373887 2012-12-10 21:58:02Z $ + */ + + /**************** +@@ -43,7 +43,6 @@ + #include + #include + #include +-#include + #include + #include + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK) +@@ -59,22 +58,11 @@ int setScheduler(struct task_struct *p, + #include + #include + +-#if 0 && (0>= 0x0600) +-#include +-#include +-#endif + +-#if defined(KEEP_ALIVE) +-/* Default KEEP_ALIVE Period is 55 sec to prevent AP from sending Keep Alive probe frame */ +-#define KEEP_ALIVE_PERIOD 55000 +-#define NULL_PKT_STR "null_pkt" +-#endif /* KEEP_ALIVE */ + /* Forward decls */ + struct dhd_bus; + struct dhd_prot; + struct dhd_info; +-struct dhd_ioctl; +-struct dhd_cmn; + + /* The level of bus communication with the dongle */ + enum dhd_bus_state { +@@ -83,41 +71,26 @@ enum dhd_bus_state { + DHD_BUS_DATA /* Ready for frame transfers */ + }; + +-#if 0 && (0>= 0x0600) +-/* Firmware requested operation mode */ +-#define STA_MASK 0x0001 +-#define HOSTAPD_MASK 0x0002 +-#define WFD_MASK 0x0004 +-#define SOFTAP_FW_MASK 0x0008 +-#define P2P_GO_ENABLED 0x0010 +-#define P2P_GC_ENABLED 0x0020 +-#define CONCURENT_MASK 0x00F0 +-#endif +- + enum dhd_op_flags { + /* Firmware requested operation mode */ +- DHD_FLAG_STA_MODE = (1 << (0)), /* STA only */ +- DHD_FLAG_HOSTAP_MODE = (1 << (1)), /* SOFTAP only */ +- DHD_FLAG_P2P_MODE = (1 << (2)), /* P2P Only */ ++ DHD_FLAG_STA_MODE = BIT(0), /* STA only */ ++ DHD_FLAG_HOSTAP_MODE = BIT(1), /* SOFTAP only */ ++ DHD_FLAG_P2P_MODE = BIT(2), /* P2P Only */ + /* STA + P2P */ + DHD_FLAG_CONCURR_SINGLE_CHAN_MODE = (DHD_FLAG_STA_MODE | DHD_FLAG_P2P_MODE), +- DHD_FLAG_CONCURR_MULTI_CHAN_MODE = (1 << (4)), /* STA + P2P */ ++ DHD_FLAG_CONCURR_MULTI_CHAN_MODE = BIT(4), /* STA + P2P */ + /* Current P2P mode for P2P connection */ +- DHD_FLAG_P2P_GC_MODE = (1 << (5)), +- DHD_FLAG_P2P_GO_MODE = (1 << (6)), +- DHD_FLAG_MBSS_MODE = (1 << (7)), /* MBSS in future */ +- DHD_FLAG_IBSS_MODE = (1 << (8)) ++ DHD_FLAG_P2P_GC_MODE = BIT(5), ++ DHD_FLAG_P2P_GO_MODE = BIT(6), ++ DHD_FLAG_MBSS_MODE = BIT(7) /* MBSS in future */ + }; + + #define MANUFACTRING_FW "WLTEST" + +-/* Max sequential TX/RX Control timeouts to set HANG event */ +-#ifndef MAX_CNTL_TX_TIMEOUT +-#define MAX_CNTL_TX_TIMEOUT 2 +-#endif /* MAX_CNTL_TX_TIMEOUT */ +-#ifndef MAX_CNTL_RX_TIMEOUT +-#define MAX_CNTL_RX_TIMEOUT 1 +-#endif /* MAX_CNTL_RX_TIMEOUT */ ++/* max sequential rxcntl timeouts to set HANG event */ ++#ifndef MAX_CNTL_TIMEOUT ++#define MAX_CNTL_TIMEOUT 2 ++#endif + + #define DHD_SCAN_ASSOC_ACTIVE_TIME 40 /* ms: Embedded default Active setting from DHD */ + #define DHD_SCAN_UNASSOC_ACTIVE_TIME 80 /* ms: Embedded def. Unassoc Active setting from DHD */ +@@ -127,7 +100,7 @@ enum dhd_op_flags { + #define POWERUP_MAX_RETRY 3 /* how many times we retry to power up the chip */ + #endif + #ifndef POWERUP_WAIT_MS +-#define POWERUP_WAIT_MS 2000 /* ms: time out in waiting wifi to come up */ ++#define POWERUP_WAIT_MS 2000 /* ms: time out in waiting wifi to come up */ + #endif + + enum dhd_bus_wake_state { +@@ -143,18 +116,20 @@ enum dhd_bus_wake_state { + WAKE_LOCK_SOFTAP_SET, + WAKE_LOCK_SOFTAP_STOP, + WAKE_LOCK_SOFTAP_START, +- WAKE_LOCK_SOFTAP_THREAD ++ WAKE_LOCK_SOFTAP_THREAD, ++ WAKE_LOCK_MAX + }; + + enum dhd_prealloc_index { + DHD_PREALLOC_PROT = 0, + DHD_PREALLOC_RXBUF, + DHD_PREALLOC_DATABUF, +- DHD_PREALLOC_OSL_BUF, + #if defined(STATIC_WL_PRIV_STRUCT) ++ DHD_PREALLOC_OSL_BUF, + DHD_PREALLOC_WIPHY_ESCAN0 = 5, ++#else ++ DHD_PREALLOC_OSL_BUF + #endif /* STATIC_WL_PRIV_STRUCT */ +- DHD_PREALLOC_DHD_INFO = 7 + }; + + typedef enum { +@@ -166,13 +141,6 @@ typedef enum { + } dhd_if_state_t; + + +-typedef enum { +- DHD_IPV6_ADDR_NONE = 0, +- DHD_IPV6_ADDR_ADD, +- DHD_IPV6_ADDR_DELETE +-} dhd_ipv6_op_t; +- +- + #if defined(CONFIG_DHD_USE_STATIC_BUF) + + uint8* dhd_os_prealloc(void *osh, int section, uint size); +@@ -203,19 +171,6 @@ typedef struct reorder_info { + uint8 pend_pkts; + } reorder_info_t; + +-#ifdef DHDTCPACK_SUPPRESS +-#define MAXTCPSTREAMS 4 /* Keep this to be power of 2 */ +-typedef struct tcp_ack_info { +- void *p_tcpackinqueue; +- uint32 tcpack_number; +- uint ip_tcp_ttllen; +- uint8 ipaddrs[8]; /* Each 4bytes src and dst IP addrs */ +- uint8 tcpports[4]; /* Each 2bytes src and dst port number */ +-} tcp_ack_info_t; +- +-void dhd_onoff_tcpack_sup(void *pub, bool on); +-#endif /* DHDTCPACK_SUPPRESS */ +- + /* Common structure for module and instance linkage */ + typedef struct dhd_pub { + /* Linkage ponters */ +@@ -223,7 +178,6 @@ typedef struct dhd_pub { + struct dhd_bus *bus; /* Bus module handle */ + struct dhd_prot *prot; /* Protocol module handle */ + struct dhd_info *info; /* Info module handle */ +- struct dhd_cmn *cmn; /* dhd_common module handle */ + + /* Internal dhd items */ + bool up; /* Driver up/down (to OS) */ +@@ -272,6 +226,10 @@ typedef struct dhd_pub { + /* Suspend disable flag and "in suspend" 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 */ ++ int pno_suspend; /* pno suspend status : "1" is pno suspended */ ++#endif /* PNO_SUPPORT */ + /* DTIM skip value, default 0(or 1) means wake each DTIM + * 3 means skip 2 DTIMs and wake up 3rd DTIM(9th beacon when AP DTIM is 3) + */ +@@ -293,64 +251,34 @@ typedef struct dhd_pub { + * For ICS MR1 releases it should be disable to be compatable with ICS MR1 Framework + * see target dhd-cdc-sdmmc-panda-cfg80211-icsmr1-gpl-debug in Makefile + */ ++/* #define WL_ENABLE_P2P_IF 1 */ + + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 + struct mutex wl_start_stop_lock; /* lock/unlock for Android start/stop */ + struct mutex wl_softap_lock; /* lock/unlock for any SoftAP/STA settings */ + #endif + ++#ifdef WLBTAMP ++ uint16 maxdatablks; ++#endif /* WLBTAMP */ + #ifdef PROP_TXSTATUS +- int wlfc_enabled; +- void* wlfc_state; +- int ptx_opt_enabled; +- bool pending_tx_pkts; +- +- /* +- * implement below functions in each platform if needed. +- */ +- /* platform specific function whether to skip flow control */ +- bool (*skip_fc)(void); +- /* platform specific function for wlfc_enable and wlfc_deinit */ +- void (*plat_enable)(void *dhd); +- void (*plat_deinit)(void *dhd); +-#endif +-#ifdef PNO_SUPPORT +- void *pno_state; +-#endif +-#ifdef ROAM_AP_ENV_DETECTION +- bool roam_env_detection; ++ int wlfc_enabled; ++ void* wlfc_state; + #endif + bool dongle_isolation; + bool dongle_trap_occured; /* flag for sending HANG event to upper layer */ + int hang_was_sent; + int rxcnt_timeout; /* counter rxcnt timeout to send HANG */ + int txcnt_timeout; /* counter txcnt timeout to send HANG */ +- bool hang_report; /* enable hang report by default */ + #ifdef WLMEDIA_HTSF + uint8 htsfdlystat_sz; /* Size of delay stats, max 255B */ + #endif +-#ifdef WLTDLS +- bool tdls_enable; +-#endif + struct reorder_info *reorder_bufs[WLHOST_REORDERDATA_MAXFLOWS]; +- char fw_capabilities[WLC_IOCTL_SMLEN]; +-#ifdef RXFRAME_THREAD +-#define MAXSKBPEND 1024 +- void *skbbuf[MAXSKBPEND]; +- uint32 store_idx; +- uint32 sent_idx; +-#endif /* RXFRAME_THREAD */ +-#ifdef DHDTCPACK_SUPPRESS +- int tcp_ack_info_cnt; +- tcp_ack_info_t tcp_ack_info_tbl[MAXTCPSTREAMS]; +-#endif /* DHDTCPACK_SUPPRESS */ ++#if defined(ARP_OFFLOAD_SUPPORT) + uint32 arp_version; ++#endif + } dhd_pub_t; + +-typedef struct dhd_cmn { +- osl_t *osh; /* OSL handle */ +- dhd_pub_t *dhd; +-} dhd_cmn_t; + + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) + +@@ -399,11 +327,6 @@ typedef struct dhd_cmn { + #undef SPINWAIT_SLEEP + #define SPINWAIT_SLEEP(a, exp, us) SPINWAIT(exp, us) + #endif /* DHDTHREAD */ +- +-#ifndef OSL_SLEEP +-#define OSL_SLEEP(ms) OSL_DELAY(ms*1000) +-#endif /* OSL_SLEEP */ +- + #define DHD_IF_VIF 0x01 /* Virtual IF (Hidden from user) */ + + unsigned long dhd_os_spin_lock(dhd_pub_t *pub); +@@ -415,7 +338,6 @@ extern int dhd_os_wake_unlock(dhd_pub_t + extern int dhd_os_wake_lock_timeout(dhd_pub_t *pub); + extern int dhd_os_wake_lock_rx_timeout_enable(dhd_pub_t *pub, int val); + extern int dhd_os_wake_lock_ctrl_timeout_enable(dhd_pub_t *pub, int val); +-extern int dhd_os_wake_lock_ctrl_timeout_cancel(dhd_pub_t *pub); + extern int dhd_os_wd_wake_lock(dhd_pub_t *pub); + extern int dhd_os_wd_wake_unlock(dhd_pub_t *pub); + +@@ -441,7 +363,7 @@ inline static void MUTEX_UNLOCK_SOFTAP_S + } + + #define DHD_OS_WAKE_LOCK(pub) dhd_os_wake_lock(pub) +-#define DHD_OS_WAKE_UNLOCK(pub) dhd_os_wake_unlock(pub) ++#define DHD_OS_WAKE_UNLOCK(pub) dhd_os_wake_unlock(pub) + #define DHD_OS_WD_WAKE_LOCK(pub) dhd_os_wd_wake_lock(pub) + #define DHD_OS_WD_WAKE_UNLOCK(pub) dhd_os_wd_wake_unlock(pub) + #define DHD_OS_WAKE_LOCK_TIMEOUT(pub) dhd_os_wake_lock_timeout(pub) +@@ -449,9 +371,7 @@ inline static void MUTEX_UNLOCK_SOFTAP_S + dhd_os_wake_lock_rx_timeout_enable(pub, val) + #define DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(pub, val) \ + dhd_os_wake_lock_ctrl_timeout_enable(pub, val) +-#define DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_CANCEL(pub) \ +- dhd_os_wake_lock_ctrl_timeout_cancel(pub) +-#define DHD_PACKET_TIMEOUT_MS 500 ++#define DHD_PACKET_TIMEOUT_MS 1000 + #define DHD_EVENT_TIMEOUT_MS 1500 + + /* interface operations (register, remove) should be atomic, use this lock to prevent race +@@ -460,6 +380,10 @@ inline static void MUTEX_UNLOCK_SOFTAP_S + void dhd_net_if_lock(struct net_device *dev); + void dhd_net_if_unlock(struct net_device *dev); + ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 ++extern struct mutex _dhd_sdio_mutex_lock_; ++#endif ++ + typedef struct dhd_if_event { + uint8 ifidx; + uint8 action; +@@ -516,9 +440,6 @@ extern void dhd_free(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); + +-/* Store the status of a connection attempt for later retrieval by an iovar */ +-extern void dhd_store_conn_status(uint32 event, uint32 status, uint32 reason); +- + extern bool dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q, void *pkt, int prec); + + /* Receive frame for delivery to OS. Callee disposes of rxp. */ +@@ -551,11 +472,6 @@ extern void dhd_os_sdunlock_txq(dhd_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); +-#ifdef DHDTCPACK_SUPPRESS +-extern void dhd_os_tcpacklock(dhd_pub_t *pub); +-extern void dhd_os_tcpackunlock(dhd_pub_t *pub); +-#endif /* DHDTCPACK_SUPPRESS */ +- + 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); +@@ -565,22 +481,29 @@ extern bool dhd_os_check_hang(dhd_pub_t + extern int dhd_os_send_hang_message(dhd_pub_t *dhdp); + extern void dhd_set_version_info(dhd_pub_t *pub, char *fw); + +-#if defined(KEEP_ALIVE) +-extern int dhd_keep_alive_onoff(dhd_pub_t *dhd); +-#endif /* KEEP_ALIVE */ +- ++#ifdef PNO_SUPPORT ++extern int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled); ++extern int dhd_pno_clean(dhd_pub_t *dhd); ++extern int dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ++ ushort scan_fr, int pno_repeat, int pno_freq_expo_max); ++extern int dhd_pno_get_status(dhd_pub_t *dhd); ++extern int dhd_dev_pno_reset(struct net_device *dev); ++extern int dhd_dev_pno_set(struct net_device *dev, wlc_ssid_t* ssids_local, ++ int nssid, ushort scan_fr, int pno_repeat, int pno_freq_expo_max); ++extern int dhd_dev_pno_enable(struct net_device *dev, int pfn_enabled); ++extern int dhd_dev_get_pno_status(struct net_device *dev); ++#endif /* PNO_SUPPORT */ + + #ifdef PKT_FILTER_SUPPORT + #define DHD_UNICAST_FILTER_NUM 0 + #define DHD_BROADCAST_FILTER_NUM 1 + #define DHD_MULTICAST4_FILTER_NUM 2 + #define DHD_MULTICAST6_FILTER_NUM 3 +-#define DHD_MDNS_FILTER_NUM 4 +-#define DHD_ARP_FILTER_NUM 5 ++#define DHD_MDNS_FILTER_NUM 4 + extern int dhd_os_enable_packet_filter(dhd_pub_t *dhdp, int val); +-extern void dhd_enable_packet_filter(int value, dhd_pub_t *dhd); +-extern int net_os_enable_packet_filter(struct net_device *dev, int val); +-extern int net_os_rxfilter_add_remove(struct net_device *dev, int val, int num); ++extern void dhd_enable_packet_filter(int value, dhd_pub_t *dhd); ++extern int net_os_enable_packet_filter(struct net_device *dev, int val); ++extern int net_os_rxfilter_add_remove(struct net_device *dev, int val, int num); + #endif /* PKT_FILTER_SUPPORT */ + + extern int dhd_get_suspend_bcn_li_dtim(dhd_pub_t *dhd); +@@ -616,8 +539,8 @@ extern void wl_event_to_host_order(wl_ev + extern int dhd_wl_ioctl(dhd_pub_t *dhd_pub, int ifindex, wl_ioctl_t *ioc, void *buf, int len); + extern int dhd_wl_ioctl_cmd(dhd_pub_t *dhd_pub, int cmd, void *arg, int len, uint8 set, + int ifindex); ++ + extern void dhd_common_init(osl_t *osh); +-extern void dhd_common_deinit(dhd_pub_t *dhd_pub, dhd_cmn_t *sa_cmn); + + extern int dhd_do_driver_init(struct net_device *net); + extern int dhd_add_if(struct dhd_info *dhd, int ifidx, void *handle, +@@ -653,7 +576,7 @@ extern int dhd_keep_alive_onoff(dhd_pub_ + #endif /* KEEP_ALIVE */ + + extern bool dhd_is_concurrent_mode(dhd_pub_t *dhd); +-extern int dhd_iovar(dhd_pub_t *pub, int ifidx, char *name, char *cmd_buf, uint cmd_len, int set); ++ + typedef enum cust_gpio_modes { + WLAN_RESET_ON, + WLAN_RESET_OFF, +@@ -673,9 +596,14 @@ extern uint dhd_watchdog_ms; + #if defined(DHD_DEBUG) + /* Console output poll interval */ + extern uint dhd_console_ms; +-extern uint wl_msg_level; + #endif /* defined(DHD_DEBUG) */ +- ++extern uint android_msg_level; ++#ifdef CONFIG_WIRELESS_EXT ++extern uint iw_msg_level; ++#endif ++#ifdef WL_CFG80211 ++extern uint wl_dbg_level; ++#endif + extern uint dhd_slpauto; + + /* Use interrupts */ +@@ -731,7 +659,7 @@ extern uint dhd_force_tx_queueing; + #ifndef CUSTOM_GLOM_SETTING + #define CUSTOM_GLOM_SETTING DEFAULT_GLOM_VALUE + #endif +-#define WL_AUTO_ROAM_TRIGGER -75 ++ + /* hooks for custom Roaming Trigger setting via Makefile */ + #define DEFAULT_ROAM_TRIGGER_VALUE -75 /* dBm default roam trigger all band */ + #define DEFAULT_ROAM_TRIGGER_SETTING -1 +@@ -753,46 +681,18 @@ extern uint dhd_force_tx_queueing; + #ifndef CUSTOM_PNO_EVENT_LOCK_xTIME + #define CUSTOM_PNO_EVENT_LOCK_xTIME DEFAULT_PNO_EVENT_LOCK_xTIME + #endif ++ + /* hooks for custom dhd_dpc_prio setting option via Makefile */ + #define DEFAULT_DHP_DPC_PRIO 1 + #ifndef CUSTOM_DPC_PRIO_SETTING + #define CUSTOM_DPC_PRIO_SETTING DEFAULT_DHP_DPC_PRIO + #endif + +-#ifndef CUSTOM_LISTEN_INTERVAL +-#define CUSTOM_LISTEN_INTERVAL LISTEN_INTERVAL +-#endif /* CUSTOM_LISTEN_INTERVAL */ +- + #define DEFAULT_SUSPEND_BCN_LI_DTIM 3 + #ifndef CUSTOM_SUSPEND_BCN_LI_DTIM + #define CUSTOM_SUSPEND_BCN_LI_DTIM DEFAULT_SUSPEND_BCN_LI_DTIM + #endif + +-#define DEFAULT_WIFI_TURNOFF_DELAY 0 +-#define WIFI_TURNOFF_DELAY DEFAULT_WIFI_TURNOFF_DELAY +- +-#ifdef RXFRAME_THREAD +-#ifndef CUSTOM_RXF_PRIO_SETTING +-#define CUSTOM_RXF_PRIO_SETTING MAX((CUSTOM_DPC_PRIO_SETTING - 1), 1) +-#endif +-#endif /* RXFRAME_THREAD */ +- +-#ifdef WLTDLS +-#ifndef CUSTOM_TDLS_IDLE_MODE_SETTING +-#define CUSTOM_TDLS_IDLE_MODE_SETTING 60000 /* 60sec to tear down TDLS of not active */ +-#endif +-#ifndef CUSTOM_TDLS_RSSI_THRESHOLD_HIGH +-#define CUSTOM_TDLS_RSSI_THRESHOLD_HIGH -70 /* rssi threshold for establishing TDLS link */ +-#endif +-#ifndef CUSTOM_TDLS_RSSI_THRESHOLD_LOW +-#define CUSTOM_TDLS_RSSI_THRESHOLD_LOW -80 /* rssi threshold for tearing down TDLS link */ +-#endif +-#endif /* WLTDLS */ +- +-#define MAX_DTIM_SKIP_BEACON_INTERVAL 100 /* max allowed associated AP beacon for DTIM skip */ +-#define MAX_DTIM_ALLOWED_INTERVAL 600 /* max allowed total beacon interval for DTIM skip */ +-#define NO_DTIM_SKIP 1 +- + #ifdef SDTEST + /* Echo packet generator (SDIO), pkts/s */ + extern uint dhd_pktgen; +@@ -809,10 +709,16 @@ extern char fw_path[MOD_PARAM_PATHLEN]; + extern char nv_path[MOD_PARAM_PATHLEN]; + + #define MOD_PARAM_INFOLEN 512 ++ + #ifdef SOFTAP + extern char fw_path2[MOD_PARAM_PATHLEN]; + #endif + ++#define FW_PATH_AUTO_SELECT 1 ++extern char firmware_path[MOD_PARAM_PATHLEN]; ++extern void dhd_bus_select_firmware_name_by_chip(struct dhd_bus *bus, char *dst, char *src); ++#define COPY_FW_PATH_BY_CHIP(bus, dst, src) dhd_bus_select_firmware_name_by_chip(bus, dst, src); ++ + /* Flag to indicate if we should download firmware on driver load */ + extern uint dhd_download_fw_on_driverload; + +@@ -821,13 +727,12 @@ extern uint dhd_download_fw_on_driverloa + #define DHD_MAX_IFS 16 + #define DHD_DEL_IF -0xe + #define DHD_BAD_IF -0xf ++#define WL_AUTO_ROAM_TRIGGER -75 + + #ifdef PROP_TXSTATUS + /* Please be mindful that total pkttag space is 32 octets only */ + typedef struct dhd_pkttag { + /* +- b[14:13] - encryption exemption +- b[12 ] - 1 = event channel + b[11 ] - 1 = this packet was sent in response to one time packet request, + do not increment credit on status for this one. [WLFC_CTL_TYPE_MAC_REQUEST_PACKET]. + b[10 ] - 1 = signal-only-packet to firmware [i.e. nothing to piggyback on] +@@ -878,12 +783,6 @@ typedef struct dhd_pkttag { + #define DHD_PKTTAG_ONETIMEPKTRQST_MASK 0x1 + #define DHD_PKTTAG_ONETIMEPKTRQST_SHIFT 11 + +-#define DHD_PKTTAG_EVENT_MASK 0x1 +-#define DHD_PKTTAG_EVENT_SHIFT 12 +- +-#define DHD_PKTTAG_EXEMPT_MASK 0x3 +-#define DHD_PKTTAG_EXEMPT_SHIFT 13 +- + #define DHD_PKTTAG_PKTDIR_MASK 0x1 + #define DHD_PKTTAG_PKTDIR_SHIFT 9 + +@@ -937,28 +836,11 @@ typedef struct dhd_pkttag { + #define DHD_PKTTAG_ONETIMEPKTRQST(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \ + DHD_PKTTAG_ONETIMEPKTRQST_SHIFT) & DHD_PKTTAG_ONETIMEPKTRQST_MASK) + +-#define DHD_PKTTAG_SETEVENT(tag, event) ((dhd_pkttag_t*)(tag))->if_flags = \ +- (((dhd_pkttag_t*)(tag))->if_flags & \ +- ~(DHD_PKTTAG_EVENT_MASK << DHD_PKTTAG_EVENT_SHIFT)) | \ +- (((event) & DHD_PKTTAG_EVENT_MASK) << DHD_PKTTAG_EVENT_SHIFT) +-#define DHD_PKTTAG_EVENT(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \ +- DHD_PKTTAG_EVENT_SHIFT) & DHD_PKTTAG_EVENT_MASK) +- +-#define DHD_PKTTAG_EXEMPT_SET(tag, value) ((dhd_pkttag_t*)(tag))->if_flags = \ +- (((dhd_pkttag_t*)(tag))->if_flags & \ +- ~(DHD_PKTTAG_EXEMPT_MASK << DHD_PKTTAG_EXEMPT_SHIFT)) | \ +- (((value) & DHD_PKTTAG_EXEMPT_MASK) << DHD_PKTTAG_EXEMPT_SHIFT) +-#define DHD_PKTTAG_EXEMPT(tag) ((((dhd_pkttag_t*)(tag))->if_flags >> \ +- DHD_PKTTAG_EXEMPT_SHIFT) & DHD_PKTTAG_EXEMPT_MASK) +- + #define DHD_PKTTAG_SETDSTN(tag, dstn_MAC_ea) memcpy(((dhd_pkttag_t*)((tag)))->dstn_ether, \ + (dstn_MAC_ea), ETHER_ADDR_LEN) + #define DHD_PKTTAG_DSTN(tag) ((dhd_pkttag_t*)(tag))->dstn_ether + +-typedef int (*f_commitpkt_t)(void* ctx, void* p); +-int dhd_os_wlfc_block(dhd_pub_t *pub); +-int dhd_os_wlfc_unblock(dhd_pub_t *pub); +-void dhd_schedule_tx(struct dhd_info *dhd); ++typedef int (*f_commitpkt_t)(void* ctx, void* p, bool wlfc_locked); + + #ifdef PROP_TXSTATUS_DEBUG + #define DHD_WLFC_CTRINC_MAC_CLOSE(entry) do { (entry)->closed_ct++; } while (0) +@@ -978,7 +860,19 @@ extern void dhd_wait_event_wakeup(dhd_pu + NdisStallExecution(1); + #define IFUNLOCK(lock) InterlockedExchange((lock), 0) + #define IFLOCK_FREE(lock) +-#define FW_SUPPORTED(dhd, capa) ((strstr(dhd->fw_capabilities, #capa) != NULL)) ++ ++#ifdef PNO_SUPPORT ++extern int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled); ++extern int dhd_pnoenable(dhd_pub_t *dhd, int pfn_enabled); ++extern int dhd_pno_clean(dhd_pub_t *dhd); ++extern int dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ++ ushort scan_fr, int pno_repeat, int pno_freq_expo_max); ++extern int dhd_pno_get_status(dhd_pub_t *dhd); ++extern int dhd_pno_set_add(dhd_pub_t *dhd, wl_pfn_t *netinfo, int nssid, ushort scan_fr, ++ ushort slowscan_fr, uint8 pno_repeat, uint8 pno_freq_expo_max, int16 flags); ++extern int dhd_pno_cfg(dhd_pub_t *dhd, wl_pfn_cfg_t *pcfg); ++extern int dhd_pno_suspend(dhd_pub_t *dhd, int pfn_suspend); ++#endif /* PNO_SUPPORT */ + #ifdef ARP_OFFLOAD_SUPPORT + #define MAX_IPV4_ENTRIES 8 + void dhd_arp_offload_set(dhd_pub_t * dhd, int arp_mode); +@@ -991,19 +885,4 @@ int dhd_arp_get_arp_hostip_table(dhd_pub + void dhd_arp_offload_add_ip(dhd_pub_t *dhd, uint32 ipaddr, int idx); + #endif /* ARP_OFFLOAD_SUPPORT */ + +-#ifdef WLTDLS +-int dhd_tdls_enable(struct net_device *dev, bool tdls_on, bool auto_on, struct ether_addr *mac); +-#endif +- +-/* Neighbor Discovery Offload Support */ +-int dhd_ndo_enable(dhd_pub_t *dhd, int ndo_enable); +-int dhd_ndo_add_ip(dhd_pub_t *dhd, char *ipaddr, int idx); +-int dhd_ndo_remove_ip(dhd_pub_t *dhd, int idx); +-/* ioctl processing for nl80211 */ +-int dhd_ioctl_process(dhd_pub_t *pub, int ifidx, struct dhd_ioctl *ioc); +- +-void dhd_set_bus_state(void *bus, uint32 state); +- +-/* Remove proper pkts(either one no-frag pkt or whole fragmented pkts) */ +-extern bool dhd_prec_drop_pkts(osl_t *osh, struct pktq *pq, int prec); + #endif /* _dhd_h_ */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/dhd_ip.c linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_ip.c +--- linux-sunxi/drivers/net/wireless/bcmdhd/dhd_ip.c 2014-01-27 01:30:30.101433269 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_ip.c 1970-01-01 01:00:00.000000000 +0100 +@@ -1,111 +0,0 @@ +-/* +- * IP Packet Parser Module. +- * +- * Copyright (C) 1999-2013, Broadcom Corporation +- * +- * Unless you and Broadcom execute a separate written software license +- * agreement governing use of this software, this software is licensed to you +- * under the terms of the GNU General Public License version 2 (the "GPL"), +- * available at http://www.broadcom.com/licenses/GPLv2.php, with the +- * following added to such license: +- * +- * As a special exception, the copyright holders of this software give you +- * permission to link this software with independent modules, and to copy and +- * distribute the resulting executable under terms of your choice, provided that +- * you also meet, for each linked independent module, the terms and conditions of +- * the license of that module. An independent module is a module which is not +- * derived from this software. The special exception does not apply to any +- * modifications of the software. +- * +- * Notwithstanding the above, under no circumstances may you combine this +- * software in any way with any other Broadcom software provided under a license +- * other than the GPL, without Broadcom's express prior written consent. +- * +- * $Id$ +- */ +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include +- +-#include +- +-#include +- +-/* special values */ +-/* 802.3 llc/snap header */ +-static const uint8 llc_snap_hdr[SNAP_HDR_LEN] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; +- +-pkt_frag_t pkt_frag_info(osl_t *osh, void *p) +-{ +- uint8 *frame; +- int length; +- uint8 *pt; /* Pointer to type field */ +- uint16 ethertype; +- struct ipv4_hdr *iph; /* IP frame pointer */ +- int ipl; /* IP frame length */ +- uint16 iph_frag; +- +- ASSERT(osh && p); +- +- frame = PKTDATA(osh, p); +- length = PKTLEN(osh, p); +- +- /* Process Ethernet II or SNAP-encapsulated 802.3 frames */ +- if (length < ETHER_HDR_LEN) { +- DHD_INFO(("%s: short eth frame (%d)\n", __FUNCTION__, length)); +- return DHD_PKT_FRAG_NONE; +- } else if (ntoh16(*(uint16 *)(frame + ETHER_TYPE_OFFSET)) >= ETHER_TYPE_MIN) { +- /* Frame is Ethernet II */ +- pt = frame + ETHER_TYPE_OFFSET; +- } else if (length >= ETHER_HDR_LEN + SNAP_HDR_LEN + ETHER_TYPE_LEN && +- !bcmp(llc_snap_hdr, frame + ETHER_HDR_LEN, SNAP_HDR_LEN)) { +- pt = frame + ETHER_HDR_LEN + SNAP_HDR_LEN; +- } else { +- DHD_INFO(("%s: non-SNAP 802.3 frame\n", __FUNCTION__)); +- return DHD_PKT_FRAG_NONE; +- } +- +- ethertype = ntoh16(*(uint16 *)pt); +- +- /* Skip VLAN tag, if any */ +- if (ethertype == ETHER_TYPE_8021Q) { +- pt += VLAN_TAG_LEN; +- +- if (pt + ETHER_TYPE_LEN > frame + length) { +- DHD_INFO(("%s: short VLAN frame (%d)\n", __FUNCTION__, length)); +- return DHD_PKT_FRAG_NONE; +- } +- +- ethertype = ntoh16(*(uint16 *)pt); +- } +- +- if (ethertype != ETHER_TYPE_IP) { +- DHD_INFO(("%s: non-IP frame (ethertype 0x%x, length %d)\n", +- __FUNCTION__, ethertype, length)); +- return DHD_PKT_FRAG_NONE; +- } +- +- iph = (struct ipv4_hdr *)(pt + ETHER_TYPE_LEN); +- ipl = length - (pt + ETHER_TYPE_LEN - frame); +- +- /* We support IPv4 only */ +- if ((ipl < IPV4_OPTIONS_OFFSET) || (IP_VER(iph) != IP_VER_4)) { +- DHD_INFO(("%s: short frame (%d) or non-IPv4\n", __FUNCTION__, ipl)); +- return DHD_PKT_FRAG_NONE; +- } +- +- iph_frag = ntoh16(iph->frag); +- +- if (iph_frag & IPV4_FRAG_DONT) { +- return DHD_PKT_FRAG_NONE; +- } else if ((iph_frag & IPV4_FRAG_MORE) == 0) { +- return DHD_PKT_FRAG_LAST; +- } else { +- return (iph_frag & IPV4_FRAG_OFFSET_MASK)? DHD_PKT_FRAG_CONT : DHD_PKT_FRAG_FIRST; +- } +-} +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/dhd_ip.h linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_ip.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/dhd_ip.h 2014-01-27 01:30:30.109433432 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_ip.h 1970-01-01 01:00:00.000000000 +0100 +@@ -1,42 +0,0 @@ +-/* +- * Header file describing the common ip parser function. +- * +- * Provides type definitions and function prototypes used to parse ip packet. +- * +- * Copyright (C) 1999-2013, Broadcom Corporation +- * +- * Unless you and Broadcom execute a separate written software license +- * agreement governing use of this software, this software is licensed to you +- * under the terms of the GNU General Public License version 2 (the "GPL"), +- * available at http://www.broadcom.com/licenses/GPLv2.php, with the +- * following added to such license: +- * +- * As a special exception, the copyright holders of this software give you +- * permission to link this software with independent modules, and to copy and +- * distribute the resulting executable under terms of your choice, provided that +- * you also meet, for each linked independent module, the terms and conditions of +- * the license of that module. An independent module is a module which is not +- * derived from this software. The special exception does not apply to any +- * modifications of the software. +- * +- * Notwithstanding the above, under no circumstances may you combine this +- * software in any way with any other Broadcom software provided under a license +- * other than the GPL, without Broadcom's express prior written consent. +- * +- * $Id$ +- */ +- +-#ifndef _dhd_ip_h_ +-#define _dhd_ip_h_ +- +-typedef enum pkt_frag +-{ +- DHD_PKT_FRAG_NONE = 0, +- DHD_PKT_FRAG_FIRST, +- DHD_PKT_FRAG_CONT, +- DHD_PKT_FRAG_LAST +-} pkt_frag_t; +- +-extern pkt_frag_t pkt_frag_info(osl_t *osh, void *p); +- +-#endif /* _dhd_ip_h_ */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/dhd_linux.c linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_linux.c +--- linux-sunxi/drivers/net/wireless/bcmdhd/dhd_linux.c 2014-02-10 11:51:00.408495958 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_linux.c 2014-02-15 00:43:44.792014069 +0100 +@@ -2,7 +2,7 @@ + * Broadcom Dongle Host Driver (DHD), Linux-specific network interface + * Basically selected code segments from usb-cdc.c and usb-rndis.c + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -22,7 +22,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: dhd_linux.c 419821 2013-08-22 21:43:26Z $ ++ * $Id: dhd_linux.c 374275 2012-12-12 11:44:18Z $ + */ + + #include +@@ -42,8 +42,7 @@ + #include + #include + #include +-#include +-#include ++#include + + #include + #include +@@ -54,7 +53,6 @@ + #include + + #include +-#include + #include + #include + #include +@@ -66,8 +64,11 @@ + #ifdef WL_CFG80211 + #include + #endif +-#ifdef PNO_SUPPORT +-#include ++ ++#ifdef WLBTAMP ++#include ++#include ++#include + #endif + + #ifdef WLMEDIA_HTSF +@@ -78,7 +79,6 @@ + #define HTSF_BUS_DELAY 150 /* assume a fix propagation in us */ + #define TSMAX 1000 /* max no. of timing record kept */ + #define NUMBIN 34 +- + static uint32 tsidx = 0; + static uint32 htsf_seqnum = 0; + uint32 tsfsync; +@@ -96,6 +96,8 @@ typedef struct histo_ { + static histo_t vi_d1, vi_d2, vi_d3, vi_d4; + #endif /* WLMEDIA_HTSF */ + ++#if defined(PKT_FILTER_SUPPORT) ++#endif /* PKT_FILTER_SUPPORT */ + + #if defined(SOFTAP) + extern bool ap_cfg_running; +@@ -126,13 +128,6 @@ static struct notifier_block dhd_notifie + .notifier_call = dhd_device_event + }; + #endif /* ARP_OFFLOAD_SUPPORT */ +-static int dhd_device_ipv6_event(struct notifier_block *this, +- unsigned long event, +- void *ptr); +- +-static struct notifier_block dhd_notifier_ipv6 = { +- .notifier_call = dhd_device_ipv6_event +-}; + + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) + #include +@@ -143,7 +138,7 @@ DECLARE_WAIT_QUEUE_HEAD(dhd_dpc_wait); + #if defined(OOB_INTR_ONLY) + extern void dhd_enable_oob_intr(struct dhd_bus *bus, bool enable); + #endif +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && (1) + static void dhd_hang_process(struct work_struct *work); + #endif + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) +@@ -162,12 +157,6 @@ MODULE_LICENSE("GPL v2"); + #endif + #endif /* BCM_FD_AGGR */ + +-#ifdef PROP_TXSTATUS +-extern bool dhd_wlfc_skip_fc(void); +-extern void dhd_wlfc_plat_enable(void *dhd); +-extern void dhd_wlfc_plat_deinit(void *dhd); +-#endif /* PROP_TXSTATUS */ +- + #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 15) + const char * + print_tainted() +@@ -177,10 +166,10 @@ print_tainted() + #endif /* LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 15) */ + + /* Linux wireless extension support */ +-#if defined(WL_WIRELESS_EXT) ++#if defined(CONFIG_WIRELESS_EXT) + #include + extern wl_iw_extra_params_t g_wl_iw_params; +-#endif /* defined(WL_WIRELESS_EXT) */ ++#endif /* defined(CONFIG_WIRELESS_EXT) */ + + #if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) + #include +@@ -191,25 +180,28 @@ extern int dhd_get_suspend_bcn_li_dtim(d + #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); +-extern void dhd_pktfilter_offload_delete(dhd_pub_t *dhd, int id); + #endif + +- + #ifdef READ_MACADDR +-extern int dhd_read_macaddr(struct dhd_info *dhd); +-#else +-static inline int dhd_read_macaddr(struct dhd_info *dhd) { return 0; } ++extern int dhd_read_macaddr(struct dhd_info *dhd, struct ether_addr *mac); ++#endif ++#ifdef RDWR_MACADDR ++extern int dhd_check_rdwr_macaddr(struct dhd_info *dhd, dhd_pub_t *dhdp, struct ether_addr *mac); ++extern int dhd_write_rdwr_macaddr(struct ether_addr *mac); + #endif + #ifdef WRITE_MACADDR + extern int dhd_write_macaddr(struct ether_addr *mac); +-#else +-static inline int dhd_write_macaddr(struct ether_addr *mac) { return 0; } + #endif +-struct ipv6_addr { +- char ipv6_addr[IPV6_ADDR_LEN]; +- dhd_ipv6_op_t ipv6_oper; +- struct list_head list; +-}; ++#ifdef GET_MAC_FROM_OTP ++extern int dhd_check_module_mac(dhd_pub_t *dhd, struct ether_addr *mac); ++#endif ++#ifdef MIMO_ANT_SETTING ++extern int dhd_sel_ant_from_file(dhd_pub_t *dhd); ++#endif ++ ++#ifdef GLOBALCONFIG_WLAN_COUNTRY_CODE ++int dhd_customer_set_country(dhd_pub_t *dhd); ++#endif + + /* Interface control information */ + typedef struct dhd_if { +@@ -226,8 +218,6 @@ typedef struct dhd_if { + char name[IFNAMSIZ+1]; /* linux interface name */ + uint8 bssidx; /* bsscfg index for the interface */ + bool set_multicast; +- struct list_head ipv6_list; +- spinlock_t ipv6_lock; + bool event2cfg80211; /* To determine if pass event to cfg80211 */ + } dhd_if_t; + +@@ -261,9 +251,9 @@ static uint32 maxdelay = 0, tspktcnt = 0 + + /* Local private structure (extension of pub) */ + typedef struct dhd_info { +-#if defined(WL_WIRELESS_EXT) ++#if defined(CONFIG_WIRELESS_EXT) + wl_iw_t iw; /* wireless extensions state (must be first) */ +-#endif /* defined(WL_WIRELESS_EXT) */ ++#endif /* defined(CONFIG_WIRELESS_EXT) */ + + dhd_pub_t pub; + +@@ -278,8 +268,6 @@ typedef struct dhd_info { + htsf_t htsf; + #endif + wait_queue_head_t ioctl_resp_wait; +- uint32 default_wd_interval; +- + struct timer_list timer; + bool wd_timer_valid; + struct tasklet_struct tasklet; +@@ -293,10 +281,6 @@ typedef struct dhd_info { + + tsk_ctl_t thr_dpc_ctl; + tsk_ctl_t thr_wdt_ctl; +-#ifdef RXFRAME_THREAD +- tsk_ctl_t thr_rxf_ctl; +- spinlock_t rxf_lock; +-#endif /* RXFRAME_THREAD */ + #endif /* DHDTHREAD */ + bool dhd_tasklet_create; + tsk_ctl_t thr_sysioc_ctl; +@@ -306,13 +290,13 @@ typedef struct dhd_info { + + /* Wakelocks */ + #if defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) +- struct wake_lock wl_wifi; /* Wifi wakelock */ +- struct wake_lock wl_rxwake; /* Wifi rx wakelock */ +- struct wake_lock wl_ctrlwake; /* Wifi ctrl wakelock */ +- struct wake_lock wl_wdwake; /* Wifi wd wakelock */ ++ struct wake_lock *wl_wifi; /* Wifi wakelock */ ++ struct wake_lock *wl_rxwake; /* Wifi rx wakelock */ ++ struct wake_lock *wl_ctrlwake; /* Wifi ctrl wakelock */ ++ struct wake_lock *wl_wdwake; /* Wifi wd wakelock */ + #endif + +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 + /* net_device interface lock, prevent race conditions among net_dev interface + * calls and wifi_on or wifi_off + */ +@@ -334,7 +318,7 @@ typedef struct dhd_info { + + #if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) + struct early_suspend early_suspend; +-#endif /* CONFIG_HAS_EARLYSUSPEND && DHD_USE_EARLYSUSPEND */ ++#endif /* CONFIG_HAS_EARLYSUSPEND && defined(DHD_USE_EARLYSUSPEND) */ + + #ifdef ARP_OFFLOAD_SUPPORT + u32 pend_ipaddr; +@@ -346,9 +330,6 @@ typedef struct dhd_info { + bool rpcth_timer_active; + bool fdaggr; + #endif +-#ifdef DHDTCPACK_SUPPRESS +- spinlock_t tcpack_lock; +-#endif /* DHDTCPACK_SUPPRESS */ + } dhd_info_t; + + /* Flag to indicate if we should download firmware on driver load */ +@@ -363,6 +344,7 @@ char nvram_path[MOD_PARAM_PATHLEN]; + /* information string to keep firmware, chio, cheip version info visiable from log */ + char info_string[MOD_PARAM_INFOLEN]; + module_param_string(info_string, info_string, MOD_PARAM_INFOLEN, 0444); ++ + int op_mode = 0; + int disable_proptx = 0; + module_param(op_mode, int, 0644); +@@ -381,32 +363,22 @@ module_param(dhd_sysioc, uint, 0); + + /* Error bits */ + module_param(dhd_msg_level, int, 0); +- +-#ifdef ARP_OFFLOAD_SUPPORT +-/* ARP offload enable */ +-uint dhd_arp_enable = TRUE; +-module_param(dhd_arp_enable, uint, 0); +- +-/* ARP offload agent mode : Enable ARP Host Auto-Reply and ARP Peer Auto-Reply */ +- +-uint dhd_arp_mode = ARP_OL_AGENT | ARP_OL_PEER_AUTO_REPLY; +- +-module_param(dhd_arp_mode, uint, 0); +-#endif /* ARP_OFFLOAD_SUPPORT */ +- +- ++#if defined(CONFIG_WIRELESS_EXT) ++module_param(iw_msg_level, int, 0); ++#endif ++#ifdef WL_CFG80211 ++module_param(wl_dbg_level, int, 0); ++#endif ++module_param(android_msg_level, int, 0); + + /* Disable Prop tx */ + module_param(disable_proptx, int, 0644); ++ + /* load firmware and/or nvram values from the filesystem */ + module_param_string(firmware_path, firmware_path, MOD_PARAM_PATHLEN, 0660); + module_param_string(nvram_path, nvram_path, MOD_PARAM_PATHLEN, 0); + + /* Watchdog interval */ +- +-/* extend watchdog expiration to 2 seconds when DPC is running */ +-#define WATCHDOG_EXTEND_INTERVAL (2000) +- + uint dhd_watchdog_ms = 10; + module_param(dhd_watchdog_ms, uint, 0); + +@@ -419,6 +391,14 @@ module_param(dhd_console_ms, uint, 0644) + uint dhd_slpauto = TRUE; + module_param(dhd_slpauto, uint, 0); + ++/* ARP offload agent mode : Enable ARP Host Auto-Reply and ARP Peer Auto-Reply */ ++uint dhd_arp_mode = ARP_OL_AGENT | ARP_OL_PEER_AUTO_REPLY; ++module_param(dhd_arp_mode, uint, 0); ++ ++/* ARP offload enable */ ++uint dhd_arp_enable = TRUE; ++module_param(dhd_arp_enable, uint, 0); ++ + #ifdef PKT_FILTER_SUPPORT + /* Global Pkt filter enable control */ + uint dhd_pkt_filter_enable = TRUE; +@@ -430,7 +410,11 @@ uint dhd_pkt_filter_init = 0; + module_param(dhd_pkt_filter_init, uint, 0); + + /* Pkt filter mode control */ ++#ifdef GAN_LITE_NAT_KEEPALIVE_FILTER ++uint dhd_master_mode = FALSE; ++#else + uint dhd_master_mode = TRUE; ++#endif /* GAL_LITE_NAT_KEEPALIVE_FILTER */ + module_param(dhd_master_mode, uint, 0); + + #ifdef DHDTHREAD +@@ -441,15 +425,9 @@ module_param(dhd_watchdog_prio, int, 0); + int dhd_dpc_prio = CUSTOM_DPC_PRIO_SETTING; + module_param(dhd_dpc_prio, int, 0); + +-#ifdef RXFRAME_THREAD +-/* RX frame thread priority */ +-int dhd_rxf_prio = CUSTOM_RXF_PRIO_SETTING; +-module_param(dhd_rxf_prio, int, 0); +-#endif /* RXFRAME_THREAD */ +- + /* DPC thread priority, -1 to use tasklet */ +-extern int dhd_dongle_ramsize; +-module_param(dhd_dongle_ramsize, int, 0); ++extern int dhd_dongle_memsize; ++module_param(dhd_dongle_memsize, int, 0); + #endif /* DHDTHREAD */ + /* Control fw roaming */ + uint dhd_roam_disable = 0; +@@ -497,6 +475,13 @@ extern void dhd_dbg_init(dhd_pub_t *dhdp + extern void dhd_dbg_remove(void); + #endif /* BCMDBGFS */ + ++/* ++ * the the 2 vars init at init time ++ *benn@cubietech.com ++ */ ++#define WL_HOST_WAKE_DEF_GPIO 2 ++int wl_host_wake_irqno = -1; ++int wl_host_wake = -1; + + + #ifdef SDTEST +@@ -546,15 +531,13 @@ int dhd_monitor_init(void *dhd_pub); + int dhd_monitor_uninit(void); + + +- +-#if defined(WL_WIRELESS_EXT) ++#if defined(CONFIG_WIRELESS_EXT) + struct iw_statistics *dhd_get_wireless_stats(struct net_device *dev); +-#endif /* defined(WL_WIRELESS_EXT) */ ++#endif /* defined(CONFIG_WIRELESS_EXT) */ + + static void dhd_dpc(ulong data); + /* forward decl */ + extern int dhd_wait_pend8021x(struct net_device *dev); +-void dhd_os_wd_timer_extend(void *bus, bool extend); + + #ifdef TOE + #ifndef BDC +@@ -567,12 +550,13 @@ static int dhd_toe_set(dhd_info_t *dhd, + static int dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata, + wl_event_msg_t *event_ptr, void **data_ptr); + +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && (LINUX_VERSION_CODE <= \ +- KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM_SLEEP) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) + static int dhd_sleep_pm_callback(struct notifier_block *nfb, unsigned long action, void *ignored) + { + int ret = NOTIFY_DONE; + ++#if defined(CONFIG_ARCH_RHEA) || defined(CONFIG_ARCH_CAPRI) || (LINUX_VERSION_CODE <= \ ++ KERNEL_VERSION(2, 6, 39)) + switch (action) { + case PM_HIBERNATION_PREPARE: + case PM_SUSPEND_PREPARE: +@@ -586,6 +570,7 @@ static int dhd_sleep_pm_callback(struct + break; + } + smp_mb(); ++#endif + return ret; + } + +@@ -595,109 +580,7 @@ static struct notifier_block dhd_sleep_p + }; + extern int register_pm_notifier(struct notifier_block *nb); + extern int unregister_pm_notifier(struct notifier_block *nb); +-#endif /* (LINUX_VERSION >= 2.6.27 && LINUX_VERSION <= 2.6.39 && CONFIG_PM_SLEEP */ +- +-#if defined(DHDTHREAD) && defined(RXFRAME_THREAD) +-/* Request scheduling of the bus rx frame */ +-static void dhd_sched_rxf(dhd_pub_t *dhdp, void *skb); +-static void dhd_os_rxflock(dhd_pub_t *pub); +-static void dhd_os_rxfunlock(dhd_pub_t *pub); +- +-static inline int dhd_rxf_enqueue(dhd_pub_t *dhdp, void* skb) +-{ +- uint32 store_idx; +- uint32 sent_idx; +- +- if (!skb) { +- DHD_ERROR(("dhd_rxf_enqueue: NULL skb!!!\n")); +- return BCME_ERROR; +- } +- +- dhd_os_rxflock(dhdp); +- store_idx = dhdp->store_idx; +- sent_idx = dhdp->sent_idx; +- if (dhdp->skbbuf[store_idx] != NULL) { +- /* Make sure the previous packets are processed */ +- /* Do I need to make this context sleep here? Definitely in Single processor case */ +- dhd_os_rxfunlock(dhdp); +- DHD_ERROR(("dhd_rxf_enqueue: pktbuf not consumed %p, store idx %d sent idx %d\n", +- skb, store_idx, sent_idx)); +- msleep(1); +- return BCME_ERROR; +- } +- DHD_TRACE(("dhd_rxf_enqueue: Store SKB %p. idx %d -> %d\n", +- skb, store_idx, (store_idx + 1) & (MAXSKBPEND - 1))); +- dhdp->skbbuf[store_idx] = skb; +- dhdp->store_idx = (store_idx + 1) & (MAXSKBPEND - 1); +- dhd_os_rxfunlock(dhdp); +- +- return BCME_OK; +-} +- +-static inline void* dhd_rxf_dequeue(dhd_pub_t *dhdp) +-{ +- uint32 store_idx; +- uint32 sent_idx; +- void *skb; +- +- dhd_os_rxflock(dhdp); +- +- store_idx = dhdp->store_idx; +- sent_idx = dhdp->sent_idx; +- skb = dhdp->skbbuf[sent_idx]; +- +- if (skb == NULL) { +- dhd_os_rxfunlock(dhdp); +- DHD_ERROR(("dhd_rxf_dequeue: Dequeued packet is NULL, store idx %d sent idx %d\n", +- store_idx, sent_idx)); +- return NULL; +- } +- +- dhdp->skbbuf[sent_idx] = NULL; +- dhdp->sent_idx = (sent_idx + 1) & (MAXSKBPEND - 1); +- +- DHD_TRACE(("dhd_rxf_dequeue: netif_rx_ni(%p), sent idx %d\n", +- skb, sent_idx)); +- +- dhd_os_rxfunlock(dhdp); +- +- return skb; +-} +-#endif /* defined(DHDTHREAD) && defined(RXFRAME_THREAD) */ +- +-static int dhd_process_cid_mac(dhd_pub_t *dhdp, bool prepost) +-{ +- dhd_info_t *dhd = (dhd_info_t *)dhdp->info; +- +- if (prepost) { /* pre process */ +- dhd_read_macaddr(dhd); +- } else { /* post process */ +- dhd_write_macaddr(&dhd->pub.mac); +- } +- +- return 0; +-} +- +-#ifdef PKT_FILTER_SUPPORT +-static bool +-_turn_on_arp_filter(dhd_pub_t *dhd, int op_mode) +-{ +- bool _apply = FALSE; +- /* In case of IBSS mode, apply arp pkt filter */ +- if (op_mode & DHD_FLAG_IBSS_MODE) { +- _apply = TRUE; +- goto exit; +- } +- /* In case of P2P GO or GC, apply pkt filter to pass arp pkt to host */ +- if ((dhd->arp_version == 1) && +- (op_mode & (DHD_FLAG_P2P_GC_MODE | DHD_FLAG_P2P_GO_MODE))) { +- _apply = TRUE; +- goto exit; +- } +-exit: +- return _apply; +-} +-#endif /* PKT_FILTER_SUPPORT */ ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */ + + void dhd_set_packet_filter(dhd_pub_t *dhd) + { +@@ -722,16 +605,17 @@ void dhd_enable_packet_filter(int value, + /* 1 - Enable packet filter, only allow unicast packet to send up */ + /* 0 - Disable packet filter */ + if (dhd_pkt_filter_enable && (!value || +- (dhd_support_sta_mode(dhd) && !dhd->dhcp_in_progress))) +- { ++ (dhd_support_sta_mode(dhd) && !dhd->dhcp_in_progress))) { + for (i = 0; i < dhd->pktfilter_count; i++) { +- if (value && (i == DHD_ARP_FILTER_NUM) && +- !_turn_on_arp_filter(dhd, dhd->op_mode)) { +- DHD_TRACE(("Do not turn on ARP white list pkt filter:" ++#ifdef PASS_ARP_PACKET ++ if (value && (i == dhd->pktfilter_count -1) && ++ !(dhd->op_mode & (DHD_FLAG_P2P_GC_MODE | DHD_FLAG_P2P_GO_MODE))) { ++ DHD_TRACE_HW4(("Do not turn on ARP white list pkt filter:" + "val %d, cnt %d, op_mode 0x%x\n", +- value, i, dhd->op_mode)); ++ value, i, dhd->op_mode)); + continue; + } ++#endif + dhd_pktfilter_offload_enable(dhd, dhd->pktfilter[i], + value, dhd_master_mode); + } +@@ -741,41 +625,52 @@ void dhd_enable_packet_filter(int value, + + static int dhd_set_suspend(int value, dhd_pub_t *dhd) + { +-#ifndef SUPPORT_PM2_ONLY ++#if !defined(SUPPORT_PM2_ONLY) + int power_mode = PM_MAX; +-#endif /* SUPPORT_PM2_ONLY */ ++#endif + /* wl_pkt_filter_enable_t enable_parm; */ + char iovbuf[32]; + int bcn_li_dtim = 0; /* Default bcn_li_dtim in resume mode is 0 */ +-#ifndef ENABLE_FW_ROAM_SUSPEND ++#ifndef DISABLE_FW_ROAM_SUSPEND + uint roamvar = 1; +-#endif /* ENABLE_FW_ROAM_SUSPEND */ +- uint nd_ra_filter = 0; +- int ret = 0; +- +- if (!dhd) +- return -ENODEV; ++#endif ++#ifdef ENABLE_BCN_LI_BCN_WAKEUP ++ int bcn_li_bcn; ++#endif /* ENABLE_BCN_LI_BCN_WAKEUP */ ++#ifdef PASS_ALL_MCAST_PKTS ++ struct dhd_info *dhdinfo = dhd->info; ++ uint32 allmulti; ++ uint i; ++#endif /* PASS_ALL_MCAST_PKTS */ + + DHD_TRACE(("%s: enter, value = %d in_suspend=%d\n", + __FUNCTION__, value, dhd->in_suspend)); + + dhd_suspend_lock(dhd); +- if (dhd->up) { ++ if (dhd && dhd->up) { + if (value && dhd->in_suspend) { + #ifdef PKT_FILTER_SUPPORT + dhd->early_suspended = 1; + #endif + /* Kernel suspended */ +- DHD_ERROR(("%s: force extra Suspend setting \n", __FUNCTION__)); ++ DHD_ERROR(("%s: force extra Suspend setting\n", __FUNCTION__)); + +-#ifndef SUPPORT_PM2_ONLY ++#if !defined(SUPPORT_PM2_ONLY) + dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, + sizeof(power_mode), TRUE, 0); +-#endif /* SUPPORT_PM2_ONLY */ +- ++#endif + /* Enable packet filter, only allow unicast packet to send up */ + dhd_enable_packet_filter(1, dhd); +- ++#ifdef PASS_ALL_MCAST_PKTS ++ allmulti = 0; ++ bcm_mkiovar("allmulti", (char *)&allmulti, ++ 4, iovbuf, sizeof(iovbuf)); ++ for (i = 0; i < DHD_MAX_IFS; i++) { ++ if (dhdinfo->iflist[i] && dhdinfo->iflist[i]->net) ++ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, ++ sizeof(iovbuf), TRUE, i); ++ } ++#endif /* PASS_ALL_MCAST_PKTS */ + + /* If DTIM skip is set up as default, force it to wake + * each third DTIM for better power savings. Note that +@@ -784,65 +679,68 @@ static int dhd_set_suspend(int value, dh + bcn_li_dtim = dhd_get_suspend_bcn_li_dtim(dhd); + bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim, + 4, iovbuf, sizeof(iovbuf)); +- if (dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), +- TRUE, 0) < 0) +- DHD_ERROR(("%s: set dtim failed\n", __FUNCTION__)); ++ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); + +-#ifndef ENABLE_FW_ROAM_SUSPEND ++#ifndef DISABLE_FW_ROAM_SUSPEND + /* Disable firmware roaming during suspend */ + bcm_mkiovar("roam_off", (char *)&roamvar, 4, + iovbuf, sizeof(iovbuf)); + dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); +-#endif /* ENABLE_FW_ROAM_SUSPEND */ +- if (FW_SUPPORTED(dhd, ndoe)) { +- /* enable IPv6 RA filter in firmware during suspend */ +- nd_ra_filter = 1; +- bcm_mkiovar("nd_ra_filter_enable", (char *)&nd_ra_filter, 4, +- iovbuf, sizeof(iovbuf)); +- if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) +- DHD_ERROR(("failed to set nd_ra_filter (%d)\n", ret)); +- } ++#endif ++#ifdef ENABLE_BCN_LI_BCN_WAKEUP ++ bcn_li_bcn = 0; ++ bcm_mkiovar("bcn_li_bcn", (char *)&bcn_li_bcn, ++ 4, iovbuf, sizeof(iovbuf)); ++ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); ++#endif /* ENABLE_BCN_LI_BCN_WAKEUP */ ++ + } else { + #ifdef PKT_FILTER_SUPPORT + dhd->early_suspended = 0; + #endif + /* Kernel resumed */ +- DHD_ERROR(("%s: Remove extra suspend setting \n", __FUNCTION__)); ++ DHD_ERROR(("%s: Remove extra suspend setting\n", __FUNCTION__)); + +-#ifndef SUPPORT_PM2_ONLY ++#if !defined(SUPPORT_PM2_ONLY) + power_mode = PM_FAST; + dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, + sizeof(power_mode), TRUE, 0); +-#endif /* SUPPORT_PM2_ONLY */ +-#ifdef PKT_FILTER_SUPPORT ++#endif + /* disable pkt filter */ + dhd_enable_packet_filter(0, dhd); +-#endif /* PKT_FILTER_SUPPORT */ ++#ifdef PASS_ALL_MCAST_PKTS ++ allmulti = 1; ++ bcm_mkiovar("allmulti", (char *)&allmulti, ++ 4, iovbuf, sizeof(iovbuf)); ++ for (i = 0; i < DHD_MAX_IFS; i++) { ++ if (dhdinfo->iflist[i] && dhdinfo->iflist[i]->net) ++ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, ++ sizeof(iovbuf), TRUE, i); ++ } ++#endif /* PASS_ALL_MCAST_PKTS */ + + /* restore pre-suspend setting for dtim_skip */ + bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim, + 4, iovbuf, sizeof(iovbuf)); + + dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); +-#ifndef ENABLE_FW_ROAM_SUSPEND ++#ifndef DISABLE_FW_ROAM_SUSPEND + roamvar = dhd_roam_disable; + bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, + sizeof(iovbuf)); + dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); +-#endif /* ENABLE_FW_ROAM_SUSPEND */ +- if (FW_SUPPORTED(dhd, ndoe)) { +- /* disable IPv6 RA filter in firmware during suspend */ +- nd_ra_filter = 0; +- bcm_mkiovar("nd_ra_filter_enable", (char *)&nd_ra_filter, 4, +- iovbuf, sizeof(iovbuf)); +- if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) +- DHD_ERROR(("failed to set nd_ra_filter (%d)\n", ret)); +- } ++#endif ++#ifdef ENABLE_BCN_LI_BCN_WAKEUP ++ bcn_li_bcn = 1; ++ bcm_mkiovar("bcn_li_bcn", (char *)&bcn_li_bcn, ++ 4, iovbuf, sizeof(iovbuf)); ++ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); ++#endif /* ENABLE_BCN_LI_BCN_WAKEUP */ + + } + } +- dhd_suspend_unlock(dhd); + ++ dhd_suspend_unlock(dhd); + return 0; + } + +@@ -882,7 +780,7 @@ static void dhd_late_resume(struct early + if (dhd) + dhd_suspend_resume_helper(dhd, 0, 0); + } +-#endif /* CONFIG_HAS_EARLYSUSPEND && DHD_USE_EARLYSUSPEND */ ++#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */ + + /* + * Generalized timeout mechanism. Uses spin sleep with exponential back-off until +@@ -1040,25 +938,31 @@ _dhd_set_multicast_list(dhd_info_t *dhd, + uint buflen; + int ret; + +- ASSERT(dhd && dhd->iflist[ifidx]); +- dev = dhd->iflist[ifidx]->net; +- if (!dev) +- return; ++ ASSERT(dhd && dhd->iflist[ifidx]); ++ dev = dhd->iflist[ifidx]->net; ++ if (!dev) ++ return; + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) +- netif_addr_lock_bh(dev); ++ netif_addr_lock_bh(dev); + #endif + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) +- cnt = netdev_mc_count(dev); ++ cnt = netdev_mc_count(dev); + #else +- cnt = dev->mc_count; ++ cnt = dev->mc_count; + #endif /* LINUX_VERSION_CODE */ + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) +- netif_addr_unlock_bh(dev); ++ netif_addr_unlock_bh(dev); + #endif + +- /* Determine initial value of allmulti flag */ ++ /* Determine initial value of allmulti flag */ + allmulti = (dev->flags & IFF_ALLMULTI) ? TRUE : FALSE; ++#ifdef PASS_ALL_MCAST_PKTS ++#ifdef PKT_FILTER_SUPPORT ++ if (!dhd->pub.early_suspended) ++#endif /* PKT_FILTER_SUPPORT */ ++ allmulti = TRUE; ++#endif /* PASS_ALL_MCAST_PKTS */ + + /* Send down the multicast list first. */ + +@@ -1078,28 +982,27 @@ _dhd_set_multicast_list(dhd_info_t *dhd, + memcpy(bufp, &cnt, sizeof(cnt)); + bufp += sizeof(cnt); + +- + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) +- netif_addr_lock_bh(dev); ++ netif_addr_lock_bh(dev); + #endif + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) +- netdev_for_each_mc_addr(ha, dev) { +- if (!cnt) +- break; +- memcpy(bufp, ha->addr, ETHER_ADDR_LEN); +- bufp += ETHER_ADDR_LEN; +- cnt--; ++ netdev_for_each_mc_addr(ha, dev) { ++ if (!cnt) ++ break; ++ memcpy(bufp, ha->addr, ETHER_ADDR_LEN); ++ bufp += ETHER_ADDR_LEN; ++ cnt--; + } + #else + for (mclist = dev->mc_list; (mclist && (cnt > 0)); + cnt--, mclist = mclist->next) { +- memcpy(bufp, (void *)mclist->dmi_addr, ETHER_ADDR_LEN); +- bufp += ETHER_ADDR_LEN; +- } ++ memcpy(bufp, (void *)mclist->dmi_addr, ETHER_ADDR_LEN); ++ bufp += ETHER_ADDR_LEN; ++ } + #endif /* LINUX_VERSION_CODE */ + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) +- netif_addr_unlock_bh(dev); ++ netif_addr_unlock_bh(dev); + #endif + + memset(&ioc, 0, sizeof(ioc)); +@@ -1154,7 +1057,6 @@ _dhd_set_multicast_list(dhd_info_t *dhd, + /* Finally, pick up the PROMISC flag as well, like the NIC driver does */ + + allmulti = (dev->flags & IFF_PROMISC) ? TRUE : FALSE; +- + allmulti = htol32(allmulti); + + memset(&ioc, 0, sizeof(ioc)); +@@ -1239,7 +1141,7 @@ dhd_op_if(dhd_if_t *ifp) + } + /* Allocate etherdev, including space for private structure */ + if (!(ifp->net = alloc_etherdev(sizeof(dhd)))) { +- DHD_ERROR(("%s: OOM - alloc_etherdev(%d)\n", __FUNCTION__, sizeof(dhd))); ++ DHD_ERROR(("%s: OOM - alloc_etherdev\n", __FUNCTION__)); + ret = -ENOMEM; + } + if (ret == 0) { +@@ -1324,23 +1226,23 @@ dhd_op_if(dhd_if_t *ifp) + } + } + +-#ifdef DHDTCPACK_SUPPRESS +-uint dhd_use_tcpack_suppress = TRUE; +-module_param(dhd_use_tcpack_suppress, uint, FALSE); +-extern bool dhd_tcpack_suppress(dhd_pub_t *dhdp, void *pkt); +-#endif /* DHDTCPACK_SUPPRESS */ +- + static int + _dhd_sysioc_thread(void *data) + { + tsk_ctl_t *tsk = (tsk_ctl_t *)data; + dhd_info_t *dhd = (dhd_info_t *)tsk->parent; +- struct ipv6_addr *iter, *next; +- int i, ret; ++ ++ ++ int i; + #ifdef SOFTAP + bool in_ap = FALSE; + unsigned long flags; + #endif ++#ifndef USE_KTHREAD_API ++ DAEMONIZE("dhd_sysioc"); ++ ++ complete(&tsk->completed); ++#endif + + while (down_interruptible(&tsk->sema) == 0) { + +@@ -1388,47 +1290,15 @@ _dhd_sysioc_thread(void *data) + if (dhd->iflist[i]->set_multicast) { + dhd->iflist[i]->set_multicast = FALSE; + _dhd_set_multicast_list(dhd, i); +- +- } +- list_for_each_entry_safe(iter, next, +- &dhd->iflist[i]->ipv6_list, list) { +- spin_lock_bh(&dhd->iflist[i]->ipv6_lock); +- list_del(&iter->list); +- spin_unlock_bh(&dhd->iflist[i]->ipv6_lock); +- if (iter->ipv6_oper == DHD_IPV6_ADDR_ADD) { +- ret = dhd_ndo_enable(&dhd->pub, TRUE); +- if (ret < 0) { +- DHD_ERROR(("%s: Enabling NDO Failed %d\n", +- __FUNCTION__, ret)); +- continue; +- } +- ret = dhd_ndo_add_ip(&dhd->pub, +- (char *)&iter->ipv6_addr[0], i); +- if (ret < 0) { +- DHD_ERROR(("%s: Adding host ip fail %d\n", +- __FUNCTION__, ret)); +- continue; +- } +- } else { +- ret = dhd_ndo_remove_ip(&dhd->pub, i); +- if (ret < 0) { +- DHD_ERROR(("%s: Removing host ip fail %d\n", +- __FUNCTION__, ret)); +- continue; +- } +- } +- NATIVE_MFREE(dhd->pub.osh, iter, sizeof(struct ipv6_addr)); + } + if (dhd->set_macaddress == i+1) { + dhd->set_macaddress = 0; + if (_dhd_set_mac_address(dhd, i, &dhd->macvalue) == 0) { + DHD_INFO(( +- "%s: MACID is overwritten\n", +- __FUNCTION__)); ++ "dhd_sysioc_thread: MACID is overwritten\n")); + } else { + DHD_ERROR(( +- "%s: _dhd_set_mac_address() failed\n", +- __FUNCTION__)); ++ "dhd_sysioc_thread: _dhd_set_mac_address() failed\n")); + } + } + } +@@ -1505,7 +1375,7 @@ uint8 prio2fifo[8] = { 1, 0, 0, 1, 2, 2, + int + dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf) + { +- int ret = BCME_OK; ++ int ret; + dhd_info_t *dhd = (dhd_info_t *)(dhdp->info); + struct ether_header *eh = NULL; + +@@ -1559,17 +1429,14 @@ dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, + #ifdef WLMEDIA_HTSF + dhd_htsf_addtxts(dhdp, pktbuf); + #endif +-#ifdef DHDTCPACK_SUPPRESS +- if (dhd_use_tcpack_suppress && dhd_tcpack_suppress(dhdp, pktbuf)) +- ret = BCME_OK; +- else +-#endif /* DHDTCPACK_SUPPRESS */ + #ifdef PROP_TXSTATUS + dhd_os_wlfc_block(dhdp); + if (dhdp->wlfc_state && ((athost_wl_status_info_t*)dhdp->wlfc_state)->proptxstatus_mode + != WLFC_FCMODE_NONE) { ++ ret = dhd_wlfc_enque_sendq(dhdp->wlfc_state, DHD_PKTTAG_FIFO(PKTTAG(pktbuf)), ++ pktbuf); + dhd_wlfc_commit_packets(dhdp->wlfc_state, (f_commitpkt_t)dhd_bus_txdata, +- dhdp->bus, pktbuf); ++ dhdp->bus); + if (((athost_wl_status_info_t*)dhdp->wlfc_state)->toggle_host_if) { + ((athost_wl_status_info_t*)dhdp->wlfc_state)->toggle_host_if = 0; + } +@@ -1578,10 +1445,10 @@ dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, + else { + dhd_os_wlfc_unblock(dhdp); + /* non-proptxstatus way */ +- ret = dhd_bus_txdata(dhdp->bus, pktbuf); ++ ret = dhd_bus_txdata(dhdp->bus, pktbuf, FALSE); + } + #else +- ret = dhd_bus_txdata(dhdp->bus, pktbuf); ++ ret = dhd_bus_txdata(dhdp->bus, pktbuf, FALSE); + #endif /* PROP_TXSTATUS */ + + return ret; +@@ -1591,10 +1458,8 @@ int + dhd_start_xmit(struct sk_buff *skb, struct net_device *net) + { + int ret; +- uint datalen; + void *pktbuf; +- dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net); +- dhd_if_t *ifp = NULL; ++ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net); + int ifidx; + #ifdef WLMEDIA_HTSF + uint8 htsfdlystat_sz = dhd->pub.htsfdlystat_sz; +@@ -1636,9 +1501,6 @@ dhd_start_xmit(struct sk_buff *skb, stru + #endif + } + +- ifp = dhd->iflist[ifidx]; +- datalen = PKTLEN(dhdp->osh, skb); +- + /* Make sure there's enough room for any header */ + + if (skb_headroom(skb) < dhd->pub.hdrlen + htsfdlystat_sz) { +@@ -1681,15 +1543,12 @@ dhd_start_xmit(struct sk_buff *skb, stru + + ret = dhd_sendpkt(&dhd->pub, ifidx, pktbuf); + ++ + done: +- if (ret) { +- ifp->stats.tx_dropped++; +- } +- else { +- dhd->pub.tx_packets++; +- ifp->stats.tx_packets++; +- ifp->stats.tx_bytes += datalen; +- } ++ if (ret) ++ dhd->pub.dstats.tx_dropped++; ++ else ++ dhd->pub.tx_packets++; + + DHD_OS_WAKE_UNLOCK(&dhd->pub); + +@@ -1779,10 +1638,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, + wl_event_msg_t event; + int tout_rx = 0; + int tout_ctrl = 0; +-#if defined(DHDTHREAD) && defined(RXFRAME_THREAD) +- void *skbhead = NULL; +- void *skbprev = NULL; +-#endif /* defined(DHDTHREAD) && defined(RXFRAME_THREAD) */ ++ + #ifdef DHD_RX_DUMP + #ifdef DHD_RX_FULL_DUMP + int k; +@@ -1794,9 +1650,10 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, + DHD_TRACE(("%s: Enter\n", __FUNCTION__)); + + for (i = 0; pktbuf && i < numpkt; i++, pktbuf = pnext) { +- +- pnext = PKTNEXT(dhdp->osh, pktbuf); +- PKTSETNEXT(wl->sh.osh, pktbuf, NULL); ++#ifdef WLBTAMP ++ struct ether_header *eh; ++ struct dot11_llc_snap_header *lsh; ++#endif + + ifp = dhd->iflist[ifidx]; + if (ifp == NULL) { +@@ -1819,6 +1676,22 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, + } + #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) */ + ++ pnext = PKTNEXT(dhdp->osh, pktbuf); ++ PKTSETNEXT(wl->sh.osh, pktbuf, NULL); ++ ++#ifdef WLBTAMP ++ eh = (struct ether_header *)PKTDATA(wl->sh.osh, pktbuf); ++ lsh = (struct dot11_llc_snap_header *)&eh[1]; ++ ++ if ((ntoh16(eh->ether_type) < ETHER_TYPE_MIN) && ++ (PKTLEN(wl->sh.osh, pktbuf) >= RFC1042_HDR_LEN) && ++ bcmp(lsh, BT_SIG_SNAP_MPROT, DOT11_LLC_SNAP_HDR_LEN - 2) == 0 && ++ lsh->type == HTON16(BTA_PROT_L2CAP)) { ++ amp_hci_ACL_data_t *ACL_data = (amp_hci_ACL_data_t *) ++ ((uint8 *)eh + RFC1042_HDR_LEN); ++ ACL_data = NULL; ++ } ++#endif /* WLBTAMP */ + + #ifdef PROP_TXSTATUS + if (dhdp->wlfc_state && PKTLEN(wl->sh.osh, pktbuf) == 0) { +@@ -1908,11 +1781,10 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, + skb_pull(skb, ETH_HLEN); + + /* Process special event packets and then discard them */ +- memset(&event, 0, sizeof(event)); + if (ntoh16(skb->protocol) == ETHER_TYPE_BRCM) { + dhd_wl_host_event(dhd, &ifidx, + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) +- skb_mac_header(skb), ++ skb->mac_header, + #else + skb->mac.raw, + #endif +@@ -1922,6 +1794,11 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, + wl_event_to_host_order(&event); + if (!tout_ctrl) + tout_ctrl = DHD_PACKET_TIMEOUT_MS; ++#ifdef WLBTAMP ++ if (event.event_type == WLC_E_BTA_HCI_EVENT) { ++ dhd_bta_doevt(dhdp, data, event.datalen); ++ } ++#endif /* WLBTAMP */ + + #if defined(PNO_SUPPORT) + if (event.event_type == WLC_E_PFN_NET_FOUND) { +@@ -1947,8 +1824,6 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, + + dhdp->dstats.rx_bytes += skb->len; + dhdp->rx_packets++; /* Local count */ +- ifp->stats.rx_bytes += skb->len; +- ifp->stats.rx_packets++; + + if (in_interrupt()) { + netif_rx(skb); +@@ -1959,13 +1834,6 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, + * by netif_rx_ni(), but in earlier kernels, we need + * to do it manually. + */ +-#if defined(DHDTHREAD) && defined(RXFRAME_THREAD) +- if (!skbhead) +- skbhead = skb; +- else +- PKTSETNEXT(wl->sh.osh, skbprev, skb); +- skbprev = skb; +-#else + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) + netif_rx_ni(skb); + #else +@@ -1975,13 +1843,9 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, + RAISE_RX_SOFTIRQ(); + local_irq_restore(flags); + #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) */ +-#endif /* defined(DHDTHREAD) && defined(RXFRAME_THREAD) */ + } + } +-#if defined(DHDTHREAD) && defined(RXFRAME_THREAD) +- if (skbhead) +- dhd_sched_rxf(dhdp, skbhead); +-#endif ++ + DHD_OS_WAKE_LOCK_RX_TIMEOUT_ENABLE(dhdp, tout_rx); + DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(dhdp, tout_ctrl); + } +@@ -1999,6 +1863,9 @@ dhd_txcomplete(dhd_pub_t *dhdp, void *tx + dhd_info_t *dhd = (dhd_info_t *)(dhdp->info); + struct ether_header *eh; + uint16 type; ++#ifdef WLBTAMP ++ uint len; ++#endif + + dhd_prot_hdrpull(dhdp, NULL, txp, NULL, NULL); + +@@ -2008,6 +1875,23 @@ dhd_txcomplete(dhd_pub_t *dhdp, void *tx + if (type == ETHER_TYPE_802_1X) + atomic_dec(&dhd->pend_8021x_cnt); + ++#ifdef WLBTAMP ++ /* Crack open the packet and check to see if it is BT HCI ACL data packet. ++ * If yes generate packet completion event. ++ */ ++ len = PKTLEN(dhdp->osh, txp); ++ ++ /* Generate ACL data tx completion event locally to avoid SDIO bus transaction */ ++ if ((type < ETHER_TYPE_MIN) && (len >= RFC1042_HDR_LEN)) { ++ struct dot11_llc_snap_header *lsh = (struct dot11_llc_snap_header *)&eh[1]; ++ ++ if (bcmp(lsh, BT_SIG_SNAP_MPROT, DOT11_LLC_SNAP_HDR_LEN - 2) == 0 && ++ ntoh16(lsh->type) == BTA_PROT_L2CAP) { ++ ++ dhd_bta_tx_hcidata_complete(dhdp, txp, success); ++ } ++ } ++#endif /* WLBTAMP */ + } + + static struct net_device_stats * +@@ -2062,6 +1946,12 @@ dhd_watchdog_thread(void *data) + dhd_watchdog_prio:(MAX_RT_PRIO-1); + setScheduler(current, SCHED_FIFO, ¶m); + } ++#ifndef USE_KTHREAD_API ++ DAEMONIZE("dhd_watchdog"); ++ ++ /* Run until signal received */ ++ complete(&tsk->completed); ++#endif + + while (1) + if (down_interruptible (&tsk->sema) == 0) { +@@ -2089,9 +1979,9 @@ dhd_watchdog_thread(void *data) + /* Reschedule the watchdog */ + if (dhd->wd_timer_valid) + mod_timer(&dhd->timer, +- jiffies + +- msecs_to_jiffies(dhd_watchdog_ms) - +- min(msecs_to_jiffies(dhd_watchdog_ms), time_lapse)); ++ jiffies + ++ msecs_to_jiffies(dhd_watchdog_ms) - ++ min(msecs_to_jiffies(dhd_watchdog_ms), time_lapse)); + dhd_os_spin_unlock(&dhd->pub, flags); + } + dhd_os_sdunlock(&dhd->pub); +@@ -2150,14 +2040,17 @@ dhd_dpc_thread(void *data) + param.sched_priority = (dhd_dpc_prio < MAX_RT_PRIO)?dhd_dpc_prio:(MAX_RT_PRIO-1); + setScheduler(current, SCHED_FIFO, ¶m); + } ++#ifndef USE_KTHREAD_API ++ DAEMONIZE("dhd_dpc"); ++ /* DHD_OS_WAKE_LOCK is called in dhd_sched_dpc[dhd_linux.c] down below */ + +-#ifdef CUSTOM_DPC_CPUCORE +- set_cpus_allowed_ptr(current, cpumask_of(CUSTOM_DPC_CPUCORE)); +-#endif /* CUSTOM_DPC_CPUCORE */ ++ /* signal: thread has started */ ++ complete(&tsk->completed); ++#endif + + /* Run until signal received */ + while (1) { +- if (!binary_sema_down(tsk)) { ++ if (down_interruptible(&tsk->sema) == 0) { + + SMP_RD_BARRIER_DEPENDS(); + if (tsk->terminated) { +@@ -2166,12 +2059,12 @@ dhd_dpc_thread(void *data) + + /* Call bus dpc unless it indicated down (then clean stop) */ + if (dhd->pub.busstate != DHD_BUS_DOWN) { +- dhd_os_wd_timer_extend(&dhd->pub, TRUE); +- while (dhd_bus_dpc(dhd->pub.bus)) { +- /* process all data */ ++ if (dhd_bus_dpc(dhd->pub.bus)) { ++ up(&tsk->sema); ++ } ++ else { ++ DHD_OS_WAKE_UNLOCK(&dhd->pub); + } +- dhd_os_wd_timer_extend(&dhd->pub, FALSE); +- DHD_OS_WAKE_UNLOCK(&dhd->pub); + } else { + if (dhd->pub.up) + dhd_bus_stop(dhd->pub.bus, TRUE); +@@ -2184,74 +2077,6 @@ dhd_dpc_thread(void *data) + + complete_and_exit(&tsk->completed, 0); + } +- +-#ifdef RXFRAME_THREAD +-static int +-dhd_rxf_thread(void *data) +-{ +- tsk_ctl_t *tsk = (tsk_ctl_t *)data; +- dhd_info_t *dhd = (dhd_info_t *)tsk->parent; +- dhd_pub_t *pub = &dhd->pub; +- +- /* This thread doesn't need any user-level access, +- * so get rid of all our resources +- */ +- if (dhd_rxf_prio > 0) +- { +- struct sched_param param; +- param.sched_priority = (dhd_rxf_prio < MAX_RT_PRIO)?dhd_rxf_prio:(MAX_RT_PRIO-1); +- setScheduler(current, SCHED_FIFO, ¶m); +- } +- +- DAEMONIZE("dhd_rxf"); +- /* DHD_OS_WAKE_LOCK is called in dhd_sched_dpc[dhd_linux.c] down below */ +- +- /* signal: thread has started */ +- complete(&tsk->completed); +- +- /* Run until signal received */ +- while (1) { +- if (down_interruptible(&tsk->sema) == 0) { +- void *skb; +-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) +- ulong flags; +-#endif +- +- SMP_RD_BARRIER_DEPENDS(); +- +- if (tsk->terminated) { +- break; +- } +- skb = dhd_rxf_dequeue(pub); +- +- if (skb == NULL) { +- continue; +- } +- while (skb) { +- void *skbnext = PKTNEXT(pub->osh, skb); +- PKTSETNEXT(pub->osh, skb, NULL); +- +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) +- netif_rx_ni(skb); +-#else +- netif_rx(skb); +- local_irq_save(flags); +- RAISE_RX_SOFTIRQ(); +- local_irq_restore(flags); +- +-#endif +- skb = skbnext; +- } +- +- DHD_OS_WAKE_UNLOCK(pub); +- } +- else +- break; +- } +- +- complete_and_exit(&tsk->completed, 0); +-} +-#endif /* RXFRAME_THREAD */ + #endif /* DHDTHREAD */ + + static void +@@ -2285,8 +2110,7 @@ dhd_sched_dpc(dhd_pub_t *dhdp) + DHD_OS_WAKE_LOCK(dhdp); + #ifdef DHDTHREAD + if (dhd->thr_dpc_ctl.thr_pid >= 0) { +- if (!binary_sema_up(&dhd->thr_dpc_ctl)) +- DHD_OS_WAKE_UNLOCK(dhdp); ++ up(&dhd->thr_dpc_ctl.sema); + return; + } + #endif /* DHDTHREAD */ +@@ -2295,35 +2119,14 @@ dhd_sched_dpc(dhd_pub_t *dhdp) + tasklet_schedule(&dhd->tasklet); + } + +-#if defined(DHDTHREAD) && defined(RXFRAME_THREAD) +-static void +-dhd_sched_rxf(dhd_pub_t *dhdp, void *skb) ++#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, uint32 *toe_ol) + { +- dhd_info_t *dhd = (dhd_info_t *)dhdp->info; +- +- DHD_OS_WAKE_LOCK(dhdp); +- +- DHD_TRACE(("dhd_sched_rxf: Enter\n")); +- +- do { +- if (dhd_rxf_enqueue(dhdp, skb) == BCME_OK) +- break; +- } while (1); +- if (dhd->thr_rxf_ctl.thr_pid >= 0) { +- up(&dhd->thr_rxf_ctl.sema); +- } +- return; +-} +-#endif /* defined(DHDTHREAD) && defined(RXFRAME_THREAD) */ +- +-#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, uint32 *toe_ol) +-{ +- wl_ioctl_t ioc; +- char buf[32]; +- int ret; ++ wl_ioctl_t ioc; ++ char buf[32]; ++ int ret; + + memset(&ioc, 0, sizeof(ioc)); + +@@ -2523,14 +2326,9 @@ dhd_ethtool(dhd_info_t *dhd, void *uaddr + + static bool dhd_check_hang(struct net_device *net, dhd_pub_t *dhdp, int error) + { +- dhd_info_t *dhd; +- +- if (!dhdp) { +- DHD_ERROR(("%s: dhdp is NULL\n", __FUNCTION__)); +- return FALSE; +- } ++ dhd_info_t * dhd; + +- if (!dhdp->up) ++ if (!dhdp) + return FALSE; + + dhd = (dhd_info_t *)dhdp->info; +@@ -2549,61 +2347,128 @@ static bool dhd_check_hang(struct net_de + return FALSE; + } + +-int dhd_ioctl_process(dhd_pub_t *pub, int ifidx, dhd_ioctl_t *ioc) ++static int ++dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd) + { +- int bcmerror = BCME_OK; ++ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net); ++ dhd_ioctl_t ioc; ++ int bcmerror = 0; + int buflen = 0; + void *buf = NULL; +- struct net_device *net; ++ uint driver = 0; ++ int ifidx; ++ int ret; + +- net = dhd_idx2net(pub, ifidx); +- if (!net) { +- bcmerror = BCME_BADARG; ++ DHD_OS_WAKE_LOCK(&dhd->pub); ++ ++ /* send to dongle only if we are not waiting for reload already */ ++ if (dhd->pub.hang_was_sent) { ++ DHD_ERROR(("%s: HANG was sent up earlier\n", __FUNCTION__)); ++ DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(&dhd->pub, DHD_EVENT_TIMEOUT_MS); ++ DHD_OS_WAKE_UNLOCK(&dhd->pub); ++ return OSL_ERROR(BCME_DONGLE_DOWN); ++ } ++ ++ ifidx = dhd_net2idx(dhd, net); ++ DHD_TRACE(("%s: ifidx %d, cmd 0x%04x\n", __FUNCTION__, ifidx, cmd)); ++ ++ if (ifidx == DHD_BAD_IF) { ++ DHD_ERROR(("%s: BAD IF\n", __FUNCTION__)); ++ DHD_OS_WAKE_UNLOCK(&dhd->pub); ++ return -1; ++ } ++ ++#if defined(CONFIG_WIRELESS_EXT) ++ /* linux wireless extensions */ ++ if ((cmd >= SIOCIWFIRST) && (cmd <= SIOCIWLAST)) { ++ /* may recurse, do NOT lock */ ++ ret = wl_iw_ioctl(net, ifr, cmd); ++ DHD_OS_WAKE_UNLOCK(&dhd->pub); ++ return ret; ++ } ++#endif /* defined(CONFIG_WIRELESS_EXT) */ ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) ++ if (cmd == SIOCETHTOOL) { ++ ret = dhd_ethtool(dhd, (void*)ifr->ifr_data); ++ DHD_OS_WAKE_UNLOCK(&dhd->pub); ++ return ret; ++ } ++#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) */ ++ ++ if (cmd == SIOCDEVPRIVATE+1) { ++ ret = wl_android_priv_cmd(net, ifr, cmd); ++ dhd_check_hang(net, &dhd->pub, ret); ++ DHD_OS_WAKE_UNLOCK(&dhd->pub); ++ return ret; ++ } ++ ++ if (cmd != SIOCDEVPRIVATE) { ++ DHD_OS_WAKE_UNLOCK(&dhd->pub); ++ 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 = BCME_BADADDR; + goto done; + } + + /* Copy out any buffer passed */ +- if (ioc->buf) { +- if (ioc->len == 0) { +- DHD_TRACE(("%s: ioc->len=0, returns BCME_BADARG \n", __FUNCTION__)); ++ if (ioc.buf) { ++ if (ioc.len == 0) { ++ DHD_TRACE(("%s: ioc.len=0, returns BCME_BADARG \n", __FUNCTION__)); + bcmerror = BCME_BADARG; + goto done; + } +- buflen = MIN(ioc->len, DHD_IOCTL_MAXLEN); ++ buflen = MIN(ioc.len, DHD_IOCTL_MAXLEN); + /* optimization for direct ioctl calls from kernel */ + /* + if (segment_eq(get_fs(), KERNEL_DS)) { +- buf = ioc->buf; ++ buf = ioc.buf; + } else { + */ + { +- if (!(buf = MALLOC(pub->osh, buflen + 1))) { ++ if (!(buf = (char*)MALLOC(dhd->pub.osh, buflen))) { + bcmerror = BCME_NOMEM; + goto done; + } +- if (copy_from_user(buf, ioc->buf, buflen)) { ++ if (copy_from_user(buf, ioc.buf, buflen)) { + bcmerror = BCME_BADADDR; + goto done; + } +- *(char *)(buf + buflen) = '\0'; + } + } + ++ /* 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 = BCME_BADADDR; ++ goto done; ++ } ++ ++ if (!capable(CAP_NET_ADMIN)) { ++ bcmerror = BCME_EPERM; ++ goto done; ++ } ++ + /* check for local dhd ioctl and handle it */ +- if (ioc->driver == DHD_IOCTL_MAGIC) { +- bcmerror = dhd_ioctl((void *)pub, ioc, buf, buflen); ++ if (driver == DHD_IOCTL_MAGIC) { ++ bcmerror = dhd_ioctl((void *)&dhd->pub, &ioc, buf, buflen); + if (bcmerror) +- pub->bcmerror = bcmerror; ++ dhd->pub.bcmerror = bcmerror; + goto done; + } + + /* send to dongle (must be up, and wl). */ +- if (pub->busstate != DHD_BUS_DATA) { ++ if (dhd->pub.busstate != DHD_BUS_DATA) { + bcmerror = BCME_DONGLE_DOWN; + goto done; + } + +- if (!pub->iswl) { ++ if (!dhd->pub.iswl) { + bcmerror = BCME_DONGLE_DOWN; + goto done; + } +@@ -2615,24 +2480,24 @@ int dhd_ioctl_process(dhd_pub_t *pub, in + * intercept WLC_DISASSOC IOCTL - serialize WPS-DONE and WLC_DISASSOC IOCTL to + * prevent disassoc frame being sent before WPS-DONE frame. + */ +- if (ioc->cmd == WLC_SET_KEY || +- (ioc->cmd == WLC_SET_VAR && ioc->buf != NULL && +- strncmp("wsec_key", ioc->buf, 9) == 0) || +- (ioc->cmd == WLC_SET_VAR && ioc->buf != NULL && +- strncmp("bsscfg:wsec_key", ioc->buf, 15) == 0) || +- ioc->cmd == WLC_DISASSOC) ++ if (ioc.cmd == WLC_SET_KEY || ++ (ioc.cmd == WLC_SET_VAR && ioc.buf != NULL && ++ strncmp("wsec_key", ioc.buf, 9) == 0) || ++ (ioc.cmd == WLC_SET_VAR && ioc.buf != NULL && ++ strncmp("bsscfg:wsec_key", ioc.buf, 15) == 0) || ++ ioc.cmd == WLC_DISASSOC) + dhd_wait_pend8021x(net); + + #ifdef WLMEDIA_HTSF +- if (ioc->buf) { ++ if (ioc.buf) { + /* short cut wl ioctl calls here */ +- if (strcmp("htsf", ioc->buf) == 0) { ++ if (strcmp("htsf", ioc.buf) == 0) { + dhd_ioctl_htsf_get(dhd, 0); + return BCME_OK; + } + +- if (strcmp("htsflate", ioc->buf) == 0) { +- if (ioc->set) { ++ if (strcmp("htsflate", ioc.buf) == 0) { ++ if (ioc.set) { + memset(ts, 0, sizeof(tstamp_t)*TSMAX); + memset(&maxdelayts, 0, sizeof(tstamp_t)); + maxdelay = 0; +@@ -2647,7 +2512,7 @@ int dhd_ioctl_process(dhd_pub_t *pub, in + } + return BCME_OK; + } +- if (strcmp("htsfclear", ioc->buf) == 0) { ++ if (strcmp("htsfclear", ioc.buf) == 0) { + memset(&vi_d1.bin, 0, sizeof(uint32)*NUMBIN); + memset(&vi_d2.bin, 0, sizeof(uint32)*NUMBIN); + memset(&vi_d3.bin, 0, sizeof(uint32)*NUMBIN); +@@ -2655,16 +2520,16 @@ int dhd_ioctl_process(dhd_pub_t *pub, in + htsf_seqnum = 0; + return BCME_OK; + } +- if (strcmp("htsfhis", ioc->buf) == 0) { ++ if (strcmp("htsfhis", ioc.buf) == 0) { + dhd_dump_htsfhisto(&vi_d1, "H to D"); + dhd_dump_htsfhisto(&vi_d2, "D to D"); + dhd_dump_htsfhisto(&vi_d3, "D to H"); + dhd_dump_htsfhisto(&vi_d4, "H to H"); + return BCME_OK; + } +- if (strcmp("tsport", ioc->buf) == 0) { +- if (ioc->set) { +- memcpy(&tsport, ioc->buf + 7, 4); ++ if (strcmp("tsport", ioc.buf) == 0) { ++ if (ioc.set) { ++ memcpy(&tsport, ioc.buf + 7, 4); + } else { + DHD_ERROR(("current timestamp port: %d \n", tsport)); + } +@@ -2673,112 +2538,28 @@ int dhd_ioctl_process(dhd_pub_t *pub, in + } + #endif /* WLMEDIA_HTSF */ + +- if ((ioc->cmd == WLC_SET_VAR || ioc->cmd == WLC_GET_VAR) && +- ioc->buf != NULL && strncmp("rpc_", ioc->buf, 4) == 0) { ++ if ((ioc.cmd == WLC_SET_VAR || ioc.cmd == WLC_GET_VAR) && ++ ioc.buf != NULL && strncmp("rpc_", ioc.buf, 4) == 0) { + #ifdef BCM_FD_AGGR +- bcmerror = dhd_fdaggr_ioctl(pub, ifidx, (wl_ioctl_t *)ioc, buf, buflen); ++ bcmerror = dhd_fdaggr_ioctl(&dhd->pub, ifidx, (wl_ioctl_t *)&ioc, buf, buflen); + #else + bcmerror = BCME_UNSUPPORTED; + #endif + goto done; + } +- bcmerror = dhd_wl_ioctl(pub, ifidx, (wl_ioctl_t *)ioc, buf, buflen); ++ bcmerror = dhd_wl_ioctl(&dhd->pub, ifidx, (wl_ioctl_t *)&ioc, buf, buflen); + + done: +- dhd_check_hang(net, pub, bcmerror); ++ dhd_check_hang(net, &dhd->pub, bcmerror); + +- if (!bcmerror && buf && ioc->buf) { +- if (copy_to_user(ioc->buf, buf, buflen)) ++ if (!bcmerror && buf && ioc.buf) { ++ if (copy_to_user(ioc.buf, buf, buflen)) + bcmerror = -EFAULT; + } + + if (buf) +- MFREE(pub->osh, buf, buflen + 1); +- +- return bcmerror; +-} +- +-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 ifidx; +- int ret; +- +- DHD_OS_WAKE_LOCK(&dhd->pub); +- +- /* send to dongle only if we are not waiting for reload already */ +- if (dhd->pub.hang_was_sent) { +- DHD_ERROR(("%s: HANG was sent up earlier\n", __FUNCTION__)); +- DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(&dhd->pub, DHD_EVENT_TIMEOUT_MS); +- DHD_OS_WAKE_UNLOCK(&dhd->pub); +- return OSL_ERROR(BCME_DONGLE_DOWN); +- } +- +- ifidx = dhd_net2idx(dhd, net); +- DHD_TRACE(("%s: ifidx %d, cmd 0x%04x\n", __FUNCTION__, ifidx, cmd)); +- +- if (ifidx == DHD_BAD_IF) { +- DHD_ERROR(("%s: BAD IF\n", __FUNCTION__)); +- DHD_OS_WAKE_UNLOCK(&dhd->pub); +- return -1; +- } +- +-#if defined(WL_WIRELESS_EXT) +- /* linux wireless extensions */ +- if ((cmd >= SIOCIWFIRST) && (cmd <= SIOCIWLAST)) { +- /* may recurse, do NOT lock */ +- ret = wl_iw_ioctl(net, ifr, cmd); +- DHD_OS_WAKE_UNLOCK(&dhd->pub); +- return ret; +- } +-#endif /* defined(WL_WIRELESS_EXT) */ +- +-#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) +- if (cmd == SIOCETHTOOL) { +- ret = dhd_ethtool(dhd, (void*)ifr->ifr_data); +- DHD_OS_WAKE_UNLOCK(&dhd->pub); +- return ret; +- } +-#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) */ +- +- if (cmd == SIOCDEVPRIVATE+1) { +- ret = wl_android_priv_cmd(net, ifr, cmd); +- dhd_check_hang(net, &dhd->pub, ret); +- DHD_OS_WAKE_UNLOCK(&dhd->pub); +- return ret; +- } +- +- if (cmd != SIOCDEVPRIVATE) { +- DHD_OS_WAKE_UNLOCK(&dhd->pub); +- 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 = BCME_BADADDR; +- goto done; +- } +- +- /* To differentiate between wl and dhd read 4 more byes */ +- if ((copy_from_user(&ioc.driver, (char *)ifr->ifr_data + sizeof(wl_ioctl_t), +- sizeof(uint)) != 0)) { +- bcmerror = BCME_BADADDR; +- goto done; +- } +- +- if (!capable(CAP_NET_ADMIN)) { +- bcmerror = BCME_EPERM; +- goto done; +- } +- +- bcmerror = dhd_ioctl_process(&dhd->pub, ifidx, &ioc); ++ MFREE(dhd->pub.osh, buf, buflen); + +-done: + DHD_OS_WAKE_UNLOCK(&dhd->pub); + + return OSL_ERROR(bcmerror); +@@ -2834,7 +2615,6 @@ dhd_stop(struct net_device *net) + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net); + DHD_OS_WAKE_LOCK(&dhd->pub); + DHD_TRACE(("%s: Enter %p\n", __FUNCTION__, net)); +- + if (dhd->pub.up == 0) { + goto exit; + } +@@ -2853,18 +2633,16 @@ dhd_stop(struct net_device *net) + * For CFG80211: Clean up all the left over virtual interfaces + * when the primary Interface is brought down. [ifconfig wlan0 down] + */ +- if (!dhd_download_fw_on_driverload) { +- if ((dhd->dhd_state & DHD_ATTACH_STATE_ADD_IF) && +- (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211)) { +- dhd_cleanup_virt_ifaces(dhd); +- } ++ if ((dhd->dhd_state & DHD_ATTACH_STATE_ADD_IF) && ++ (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211)) { ++ dhd_cleanup_virt_ifaces(dhd); + } + } + #endif + + #ifdef PROP_TXSTATUS + dhd_os_wlfc_block(&dhd->pub); +- dhd_wlfc_cleanup(&dhd->pub, NULL, 0); ++ dhd_wlfc_cleanup(&dhd->pub); + dhd_os_wlfc_unblock(&dhd->pub); + #endif + /* Stop the protocol module */ +@@ -2873,8 +2651,10 @@ dhd_stop(struct net_device *net) + OLD_MOD_DEC_USE_COUNT; + exit: + #if defined(WL_CFG80211) +- if (ifidx == 0 && !dhd_download_fw_on_driverload) +- wl_android_wifi_off(net); ++ if (ifidx == 0) { ++ if (!dhd_download_fw_on_driverload) ++ wl_android_wifi_off(net); ++ } + #endif + dhd->pub.rxcnt_timeout = 0; + dhd->pub.txcnt_timeout = 0; +@@ -2893,18 +2673,24 @@ dhd_open(struct net_device *net) + int ifidx; + int32 ret = 0; + ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 ++ if (mutex_is_locked(&_dhd_sdio_mutex_lock_) != 0) { ++ DHD_ERROR(("%s : dhd_open: call dev open before insmod complete!\n", __FUNCTION__)); ++ } ++ mutex_lock(&_dhd_sdio_mutex_lock_); ++#endif ++ ++ printk("%s, firmware path %s\n", __func__, firmware_path); ++ + DHD_OS_WAKE_LOCK(&dhd->pub); + /* Update FW path if it was changed */ + if (strlen(firmware_path) != 0) { + if (firmware_path[strlen(firmware_path)-1] == '\n') + firmware_path[strlen(firmware_path)-1] = '\0'; +- bzero(fw_path, MOD_PARAM_PATHLEN); +- strncpy(fw_path, firmware_path, sizeof(fw_path)-1); +- firmware_path[0] = '\0'; ++ COPY_FW_PATH_BY_CHIP( dhd->pub.bus, fw_path, firmware_path); + } + + +- + dhd->pub.dongle_trap_occured = 0; + dhd->pub.hang_was_sent = 0; + #if !defined(WL_CFG80211) +@@ -2919,8 +2705,7 @@ dhd_open(struct net_device *net) + ret = -1; + goto exit; + } +- +-#endif ++#endif + + ifidx = dhd_net2idx(dhd, net); + DHD_TRACE(("%s: ifidx %d\n", __FUNCTION__, ifidx)); +@@ -2944,11 +2729,11 @@ dhd_open(struct net_device *net) + if (!dhd_download_fw_on_driverload) { + ret = wl_android_wifi_on(net); + if (ret != 0) { +- DHD_ERROR(("%s : wl_android_wifi_on failed (%d)\n", +- __FUNCTION__, ret)); ++ DHD_ERROR(("%s: failed with code %d\n", __FUNCTION__, ret)); + ret = -1; + goto exit; + } ++ } else { + } + #endif + +@@ -2997,6 +2782,10 @@ exit: + dhd_stop(net); + + DHD_OS_WAKE_UNLOCK(&dhd->pub); ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 ++ mutex_unlock(&_dhd_sdio_mutex_lock_); ++#endif + return ret; + } + +@@ -3009,6 +2798,15 @@ int dhd_do_driver_init(struct net_device + return -EINVAL; + } + ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 ++#ifdef MULTIPLE_SUPPLICANT ++ if (mutex_is_locked(&_dhd_sdio_mutex_lock_) != 0) { ++ DHD_ERROR(("%s : dhdsdio_probe is already running!\n", __FUNCTION__)); ++ return 0; ++ } ++#endif /* MULTIPLE_SUPPLICANT */ ++#endif ++ + dhd = *(dhd_info_t **)netdev_priv(net); + + /* If driver is already initialized, do nothing +@@ -3039,7 +2837,7 @@ dhd_osl_detach(osl_t *osh) + DHD_ERROR(("%s: MEMORY LEAK %d bytes\n", __FUNCTION__, MALLOCED(osh))); + } + osl_detach(osh); +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) ++#if 1 && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) + dhd_registration_check = FALSE; + up(&dhd_registration_sem); + #if defined(BCMLXSDMMC) +@@ -3067,7 +2865,7 @@ dhd_add_if(dhd_info_t *dhd, int ifidx, v + } + } else + if ((ifp = MALLOC(dhd->pub.osh, sizeof(dhd_if_t))) == NULL) { +- DHD_ERROR(("%s: OOM - dhd_if_t(%d)\n", __FUNCTION__, sizeof(dhd_if_t))); ++ DHD_ERROR(("%s: OOM - dhd_if_t\n", __FUNCTION__)); + return -ENOMEM; + } + +@@ -3077,8 +2875,6 @@ dhd_add_if(dhd_info_t *dhd, int ifidx, v + dhd->iflist[ifidx] = ifp; + strncpy(ifp->name, name, IFNAMSIZ); + ifp->name[IFNAMSIZ] = '\0'; +- INIT_LIST_HEAD(&ifp->ipv6_list); +- spin_lock_init(&ifp->ipv6_lock); + if (mac_addr != NULL) + memcpy(&ifp->mac_addr, mac_addr, ETHER_ADDR_LEN); + +@@ -3155,14 +2951,14 @@ dhd_attach(osl_t *osh, struct dhd_bus *b + dhd_attach_states_t dhd_state = DHD_ATTACH_STATE_INIT; + DHD_TRACE(("%s: Enter\n", __FUNCTION__)); + ++ printk("%s, firmware path %s\n", __func__, firmware_path); ++ + /* updates firmware nvram path if it was provided as module parameters */ +- if (strlen(firmware_path) != 0) { +- bzero(fw_path, MOD_PARAM_PATHLEN); +- strncpy(fw_path, firmware_path, sizeof(fw_path) - 1); +- } ++ if ((firmware_path != NULL) && (firmware_path[0] != '\0')) ++ COPY_FW_PATH_BY_CHIP(bus, fw_path, firmware_path); + if (strlen(nvram_path) != 0) { +- bzero(nv_path, MOD_PARAM_PATHLEN); + strncpy(nv_path, nvram_path, sizeof(nv_path) -1); ++ nv_path[sizeof(nv_path) -1] = '\0'; + } + + /* Allocate etherdev, including space for private structure */ +@@ -3173,18 +2969,10 @@ dhd_attach(osl_t *osh, struct dhd_bus *b + dhd_state |= DHD_ATTACH_STATE_NET_ALLOC; + + /* Allocate primary dhd_info */ +-#if defined(CONFIG_DHD_USE_STATIC_BUF) +- dhd = (void *)dhd_os_prealloc(osh, DHD_PREALLOC_DHD_INFO, sizeof(dhd_info_t)); +- if (!dhd) { +- DHD_INFO(("%s: OOM - Pre-alloc dhd_info\n", __FUNCTION__)); +-#endif /* CONFIG_DHD_USE_STATIC_BUF */ + if (!(dhd = MALLOC(osh, sizeof(dhd_info_t)))) { + DHD_ERROR(("%s: OOM - alloc dhd_info\n", __FUNCTION__)); + goto fail; + } +-#if defined(CONFIG_DHD_USE_STATIC_BUF) +- } +-#endif /* CONFIG_DHD_USE_STATIC_BUF */ + memset(dhd, 0, sizeof(dhd_info_t)); + + #ifdef DHDTHREAD +@@ -3236,15 +3024,8 @@ dhd_attach(osl_t *osh, struct dhd_bus *b + #ifdef PROP_TXSTATUS_VSDB + dhd->pub.wlfc_enabled = FALSE; + #else +- if (!disable_proptx) +- dhd->pub.wlfc_enabled = TRUE; +- else +- dhd->pub.wlfc_enabled = FALSE; ++ dhd->pub.wlfc_enabled = TRUE; + #endif /* PROP_TXSTATUS_VSDB */ +- dhd->pub.ptx_opt_enabled = FALSE; +- dhd->pub.skip_fc = dhd_wlfc_skip_fc; +- dhd->pub.plat_enable = dhd_wlfc_plat_enable; +- dhd->pub.plat_deinit = dhd_wlfc_plat_deinit; + #endif /* PROP_TXSTATUS */ + + /* Initialize other structure content */ +@@ -3255,12 +3036,6 @@ dhd_attach(osl_t *osh, struct dhd_bus *b + spin_lock_init(&dhd->sdlock); + spin_lock_init(&dhd->txqlock); + spin_lock_init(&dhd->dhd_lock); +-#if defined(DHDTHREAD) && defined(RXFRAME_THREAD) +- spin_lock_init(&dhd->rxf_lock); +-#endif /* defined(DHDTHREAD) && defined(RXFRAME_THREAD) */ +-#ifdef DHDTCPACK_SUPPRESS +- spin_lock_init(&dhd->tcpack_lock); +-#endif /* DHDTCPACK_SUPPRESS */ + + /* Initialize Wakelock stuff */ + spin_lock_init(&dhd->wakelock_spinlock); +@@ -3269,12 +3044,20 @@ dhd_attach(osl_t *osh, struct dhd_bus *b + dhd->wakelock_rx_timeout_enable = 0; + dhd->wakelock_ctrl_timeout_enable = 0; + #ifdef CONFIG_HAS_WAKELOCK +- wake_lock_init(&dhd->wl_wifi, WAKE_LOCK_SUSPEND, "wlan_wake"); +- wake_lock_init(&dhd->wl_rxwake, WAKE_LOCK_SUSPEND, "wlan_rx_wake"); +- wake_lock_init(&dhd->wl_ctrlwake, WAKE_LOCK_SUSPEND, "wlan_ctrl_wake"); +- wake_lock_init(&dhd->wl_wdwake, WAKE_LOCK_SUSPEND, "wlan_wd_wake"); ++ dhd->wl_wifi = MALLOC(osh, sizeof(struct wake_lock)); ++ dhd->wl_rxwake = MALLOC(osh, sizeof(struct wake_lock)); ++ dhd->wl_ctrlwake = MALLOC(osh, sizeof(struct wake_lock)); ++ dhd->wl_wdwake = MALLOC(osh, sizeof(struct wake_lock)); ++ if (!dhd->wl_wifi || !dhd->wl_rxwake || !dhd->wl_ctrlwake || !dhd->wl_wdwake) { ++ DHD_ERROR(("%s: mem alloc for wake lock failed\n", __FUNCTION__)); ++ goto fail; ++ } ++ wake_lock_init(dhd->wl_wifi, WAKE_LOCK_SUSPEND, "wlan_wake"); ++ wake_lock_init(dhd->wl_rxwake, WAKE_LOCK_SUSPEND, "wlan_rx_wake"); ++ wake_lock_init(dhd->wl_ctrlwake, WAKE_LOCK_SUSPEND, "wlan_ctrl_wake"); ++ wake_lock_init(dhd->wl_wdwake, WAKE_LOCK_SUSPEND, "wlan_wd_wake"); + #endif /* CONFIG_HAS_WAKELOCK */ +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 + mutex_init(&dhd->dhd_net_if_mutex); + mutex_init(&dhd->dhd_suspend_mutex); + #endif +@@ -3297,23 +3080,22 @@ dhd_attach(osl_t *osh, struct dhd_bus *b + dhd_monitor_init(&dhd->pub); + dhd_state |= DHD_ATTACH_STATE_CFG80211; + #endif +-#if defined(WL_WIRELESS_EXT) ++#if defined(CONFIG_WIRELESS_EXT) + /* Attach and link in the iw */ + if (!(dhd_state & DHD_ATTACH_STATE_CFG80211)) { + if (wl_iw_attach(net, (void *)&dhd->pub) != 0) { +- DHD_ERROR(("wl_iw_attach failed\n")); +- goto fail; +- } ++ DHD_ERROR(("wl_iw_attach failed\n")); ++ goto fail; ++ } + dhd_state |= DHD_ATTACH_STATE_WL_ATTACH; + } +-#endif /* defined(WL_WIRELESS_EXT) */ ++#endif /* defined(CONFIG_WIRELESS_EXT) */ + + + /* Set up the watchdog timer */ + init_timer(&dhd->timer); + dhd->timer.data = (ulong)dhd; + dhd->timer.function = dhd_watchdog; +- dhd->default_wd_interval = dhd_watchdog_ms; + + #ifdef DHDTHREAD + /* Initialize thread based operation and lock */ +@@ -3327,8 +3109,11 @@ dhd_attach(osl_t *osh, struct dhd_bus *b + + if (dhd_watchdog_prio >= 0) { + /* Initialize watchdog thread */ +- PROC_START(dhd_watchdog_thread, dhd, &dhd->thr_wdt_ctl, 0, "dhd_watchdog_thread"); +- ++#ifdef USE_KTHREAD_API ++ PROC_START2(dhd_watchdog_thread, dhd, &dhd->thr_wdt_ctl, 0, "dhd_watchdog_thread"); ++#else ++ PROC_START(dhd_watchdog_thread, dhd, &dhd->thr_wdt_ctl, 0); ++#endif + } else { + dhd->thr_wdt_ctl.thr_pid = -1; + } +@@ -3336,17 +3121,16 @@ dhd_attach(osl_t *osh, struct dhd_bus *b + /* Set up the bottom half handler */ + if (dhd_dpc_prio >= 0) { + /* Initialize DPC thread */ +- PROC_START(dhd_dpc_thread, dhd, &dhd->thr_dpc_ctl, 0, "dhd_dpc"); ++#ifdef USE_KTHREAD_API ++ PROC_START2(dhd_dpc_thread, dhd, &dhd->thr_dpc_ctl, 0, "dhd_dpc"); ++#else ++ PROC_START(dhd_dpc_thread, dhd, &dhd->thr_dpc_ctl, 0); ++#endif + } else { + /* use tasklet for dpc */ + tasklet_init(&dhd->tasklet, dhd_dpc, (ulong)dhd); + dhd->thr_dpc_ctl.thr_pid = -1; + } +-#ifdef RXFRAME_THREAD +- bzero(&dhd->pub.skbbuf[0], sizeof(void *) * MAXSKBPEND); +- /* Initialize RXF thread */ +- PROC_START(dhd_rxf_thread, dhd, &dhd->thr_rxf_ctl, 0, "dhd_rxf"); +-#endif + #else + /* Set up the bottom half handler */ + tasklet_init(&dhd->tasklet, dhd_dpc, (ulong)dhd); +@@ -3354,25 +3138,26 @@ dhd_attach(osl_t *osh, struct dhd_bus *b + #endif /* DHDTHREAD */ + + if (dhd_sysioc) { +- PROC_START(_dhd_sysioc_thread, dhd, &dhd->thr_sysioc_ctl, 0, "dhd_sysioc"); ++#ifdef USE_KTHREAD_API ++ PROC_START2(_dhd_sysioc_thread, dhd, &dhd->thr_sysioc_ctl, 0, "dhd_sysioc"); ++#else ++ PROC_START(_dhd_sysioc_thread, dhd, &dhd->thr_sysioc_ctl, 0); ++#endif + } else { + dhd->thr_sysioc_ctl.thr_pid = -1; + } + dhd_state |= DHD_ATTACH_STATE_THREADS_CREATED; +- +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && (1) + INIT_WORK(&dhd->work_hang, dhd_hang_process); + #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ +- + /* + * Save the dhd_info into the priv + */ + memcpy(netdev_priv(net), &dhd, sizeof(dhd)); + +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && (LINUX_VERSION_CODE <= \ +- KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM_SLEEP) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) + register_pm_notifier(&dhd_sleep_pm_notifier); +-#endif /* (LINUX_VERSION >= 2.6.27 && LINUX_VERSION <= 2.6.39 && CONFIG_PM_SLEEP */ ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */ + + #if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) + dhd->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 20; +@@ -3380,20 +3165,12 @@ dhd_attach(osl_t *osh, struct dhd_bus *b + dhd->early_suspend.resume = dhd_late_resume; + register_early_suspend(&dhd->early_suspend); + dhd_state |= DHD_ATTACH_STATE_EARLYSUSPEND_DONE; +-#endif /* CONFIG_HAS_EARLYSUSPEND && DHD_USE_EARLYSUSPEND */ ++#endif + + #ifdef ARP_OFFLOAD_SUPPORT + dhd->pend_ipaddr = 0; + register_inetaddr_notifier(&dhd_notifier); + #endif /* ARP_OFFLOAD_SUPPORT */ +-#ifdef IPV6 +- register_inet6addr_notifier(&dhd_notifier_ipv6); +-#endif +- +-#ifdef DHDTCPACK_SUPPRESS +- dhd->pub.tcp_ack_info_cnt = 0; +- bzero(dhd->pub.tcp_ack_info_tbl, sizeof(struct tcp_ack_info)*MAXTCPSTREAMS); +-#endif /* DHDTCPACK_SUPPRESS */ + + dhd_state |= DHD_ATTACH_STATE_DONE; + dhd->dhd_state = dhd_state; +@@ -3432,19 +3209,8 @@ dhd_bus_start(dhd_pub_t *dhdp) + + /* try to download image and nvram to the dongle */ + if ((dhd->pub.busstate == DHD_BUS_DOWN) && +- (fw_path[0] != '\0') && (nv_path[0] != '\0')) { +-#ifdef SHOW_NVRAM_TYPE +- { /* Show nvram type in the kernel log */ +- int i; +- for (i = 0; nv_path[i] != '\0'; ++i) { +- if (nv_path[i] == '.') { +- ++i; +- break; +- } +- } +- DHD_ERROR(("%s: nvram_type = [%s]\n", __FUNCTION__, &nv_path[i])); +- } +-#endif /* SHOW_NVRAM_TYPE */ ++ (fw_path != NULL) && (fw_path[0] != '\0') && ++ (nv_path != NULL) && (nv_path[0] != '\0')) { + /* wake lock moved to dhdsdio_download_firmware */ + if (!(dhd_bus_download_firmware(dhd->pub.bus, dhd->pub.osh, + fw_path, nv_path))) { +@@ -3479,6 +3245,7 @@ dhd_bus_start(dhd_pub_t *dhdp) + #endif /* DHDTHREAD */ + return ret; + } ++ bcmsdh_set_drvdata(dhdp); + #if defined(OOB_INTR_ONLY) + /* Host registration for OOB interrupt */ + if (bcmsdh_register_oob_intr(dhdp)) { +@@ -3488,7 +3255,6 @@ dhd_bus_start(dhd_pub_t *dhdp) + dhd->wd_timer_valid = FALSE; + dhd_os_spin_unlock(&dhd->pub, flags); + del_timer_sync(&dhd->timer); +- + DHD_ERROR(("%s Host failed to register for OOB\n", __FUNCTION__)); + #ifdef DHDTHREAD + if (dhd->threads_only) +@@ -3522,13 +3288,23 @@ dhd_bus_start(dhd_pub_t *dhdp) + dhd_os_sdunlock(dhdp); + #endif /* DHDTHREAD */ + +- dhd_process_cid_mac(dhdp, TRUE); ++#ifdef BCMSDIOH_TXGLOM ++ if ((dhd->pub.busstate == DHD_BUS_DATA) && bcmsdh_glom_enabled()) { ++ dhd_txglom_enable(dhdp, TRUE); ++ } ++#endif ++ ++#ifdef READ_MACADDR ++ dhd_read_macaddr(dhd); ++#endif + + /* Bus is ready, do any protocol initialization */ + if ((ret = dhd_prot_init(&dhd->pub)) < 0) + return ret; + +- dhd_process_cid_mac(dhdp, FALSE); ++#ifdef WRITE_MACADDR ++ dhd_write_macaddr(dhd->pub.mac.octet); ++#endif + + #ifdef ARP_OFFLOAD_SUPPORT + if (dhd->pend_ipaddr) { +@@ -3542,73 +3318,6 @@ dhd_bus_start(dhd_pub_t *dhdp) + return 0; + } + +-#ifdef WLTDLS +-int _dhd_tdls_enable(dhd_pub_t *dhd, bool tdls_on, bool auto_on, struct ether_addr *mac) +-{ +- char iovbuf[WLC_IOCTL_SMLEN]; +- uint32 tdls = tdls_on; +- int ret = 0; +- uint32 tdls_auto_op = 0; +- uint32 tdls_idle_time = CUSTOM_TDLS_IDLE_MODE_SETTING; +- int32 tdls_rssi_high = CUSTOM_TDLS_RSSI_THRESHOLD_HIGH; +- int32 tdls_rssi_low = CUSTOM_TDLS_RSSI_THRESHOLD_LOW; +- if (!FW_SUPPORTED(dhd, tdls)) +- return BCME_ERROR; +- +- if (dhd->tdls_enable == tdls_on) +- goto auto_mode; +- bcm_mkiovar("tdls_enable", (char *)&tdls, sizeof(tdls), iovbuf, sizeof(iovbuf)); +- if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) { +- DHD_ERROR(("%s: tdls %d failed %d\n", __FUNCTION__, tdls, ret)); +- goto exit; +- } +- dhd->tdls_enable = tdls_on; +-auto_mode: +- if (mac) { +- tdls_auto_op = auto_on; +- bcm_mkiovar("tdls_auto_op", (char *)&tdls_auto_op, sizeof(tdls_auto_op), +- iovbuf, sizeof(iovbuf)); +- if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, +- sizeof(iovbuf), TRUE, 0)) < 0) { +- DHD_ERROR(("%s: tdls_auto_op failed %d\n", __FUNCTION__, ret)); +- goto exit; +- } +- +- if (tdls_auto_op) { +- bcm_mkiovar("tdls_idle_time", (char *)&tdls_idle_time, +- sizeof(tdls_idle_time), iovbuf, sizeof(iovbuf)); +- if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, +- sizeof(iovbuf), TRUE, 0)) < 0) { +- DHD_ERROR(("%s: tdls_idle_time failed %d\n", __FUNCTION__, ret)); +- goto exit; +- } +- bcm_mkiovar("tdls_rssi_high", (char *)&tdls_rssi_high, 4, iovbuf, sizeof(iovbuf)); +- if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) { +- DHD_ERROR(("%s: tdls_rssi_high failed %d\n", __FUNCTION__, ret)); +- goto exit; +- } +- bcm_mkiovar("tdls_rssi_low", (char *)&tdls_rssi_low, 4, iovbuf, sizeof(iovbuf)); +- if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) { +- DHD_ERROR(("%s: tdls_rssi_low failed %d\n", __FUNCTION__, ret)); +- goto exit; +- } +- } +- } +-exit: +- return ret; +-} +-int dhd_tdls_enable(struct net_device *dev, bool tdls_on, bool auto_on, struct ether_addr *mac) +-{ +- dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); +- int ret = 0; +- if (dhd) +- ret = _dhd_tdls_enable(&dhd->pub, tdls_on, auto_on, mac); +- else +- ret = BCME_ERROR; +- return ret; +-} +-#endif /* WLTDLS */ +- + bool dhd_is_concurrent_mode(dhd_pub_t *dhd) + { + if (!dhd) +@@ -3640,10 +3349,18 @@ dhd_get_concurrent_capabilites(dhd_pub_t + */ + if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) + return 0; +- if (FW_SUPPORTED(dhd, vsdb)) { ++ memset(buf, 0, sizeof(buf)); ++ bcm_mkiovar("cap", 0, 0, buf, sizeof(buf)); ++ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf), ++ FALSE, 0)) < 0) { ++ DHD_ERROR(("%s: Get Capability failed (error=%d)\n", ++ __FUNCTION__, ret)); ++ return 0; ++ } ++ if (strstr(buf, "vsdb")) { + mchan_supported = TRUE; + } +- if (!FW_SUPPORTED(dhd, p2p)) { ++ if (strstr(buf, "p2p") == NULL) { + DHD_TRACE(("Chip does not support p2p\n")); + return 0; + } +@@ -3664,7 +3381,7 @@ dhd_get_concurrent_capabilites(dhd_pub_t + ret = DHD_FLAG_CONCURR_SINGLE_CHAN_MODE; + if (mchan_supported) + ret |= DHD_FLAG_CONCURR_MULTI_CHAN_MODE; +-#if defined(WL_ENABLE_P2P_IF) || defined(WL_CFG80211_P2P_DEV_IF) ++#if defined(WL_ENABLE_P2P_IF) + /* For customer_hw4, although ICS, + * we still support concurrent mode + */ +@@ -3677,21 +3394,28 @@ dhd_get_concurrent_capabilites(dhd_pub_t + } + return 0; + } +-#endif ++#endif + int + dhd_preinit_ioctls(dhd_pub_t *dhd) + { + int ret = 0; + char eventmask[WL_EVENTING_MASK_LEN]; + char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */ +- uint32 buf_key_b4_m4 = 1; +-#ifdef CUSTOM_AMPDU_BA_WSIZE +- uint32 ampdu_ba_wsize = CUSTOM_AMPDU_BA_WSIZE; +-#endif /* CUSTOM_AMPDU_BA_WSIZE */ ++ ++#if !defined(WL_CFG80211) ++ uint up = 0; ++#endif /* !defined(WL_CFG80211) */ + uint power_mode = PM_FAST; + uint32 dongle_align = DHD_SDALIGN; + uint32 glom = CUSTOM_GLOM_SETTING; ++#if defined(VSDB) || defined(ROAM_ENABLE) ++ uint bcn_timeout = 8; ++#else + uint bcn_timeout = 4; ++#endif ++#ifdef ENABLE_BCN_LI_BCN_WAKEUP ++ uint32 bcn_li_bcn = 1; ++#endif /* ENABLE_BCN_LI_BCN_WAKEUP */ + uint retry_max = 3; + #if defined(ARP_OFFLOAD_SUPPORT) + int arpoe = 1; +@@ -3701,15 +3425,12 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) + int scan_passive_time = DHD_SCAN_PASSIVE_TIME; + char buf[WLC_IOCTL_SMLEN]; + char *ptr; +- uint32 listen_interval = CUSTOM_LISTEN_INTERVAL; /* Default Listen Interval in Beacons */ ++ uint32 listen_interval = LISTEN_INTERVAL; /* Default Listen Interval in Beacons */ + #ifdef ROAM_ENABLE + uint roamvar = 0; + int roam_trigger[2] = {CUSTOM_ROAM_TRIGGER_SETTING, WLC_BAND_ALL}; + int roam_scan_period[2] = {10, WLC_BAND_ALL}; + int roam_delta[2] = {CUSTOM_ROAM_DELTA_SETTING, WLC_BAND_ALL}; +-#ifdef ROAM_AP_ENV_DETECTION +- int roam_env_mode = AP_ENV_INDETERMINATE; +-#endif /* ROAM_AP_ENV_DETECTION */ + #ifdef FULL_ROAMING_SCAN_PERIOD_60_SEC + int roam_fullscan_period = 60; + #else /* FULL_ROAMING_SCAN_PERIOD_60_SEC */ +@@ -3728,6 +3449,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) + uint32 mpc = 0; /* Turn MPC off for AP/APSTA mode */ + struct ether_addr p2p_ea; + #endif ++ uint32 mimo_bw_cap = 1; /* Turn HT40 on in 2.4 GHz */ + + #if defined(AP) || defined(WLP2P) + uint32 apsta = 1; /* Enable APSTA mode */ +@@ -3735,36 +3457,22 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) + #ifdef GET_CUSTOM_MAC_ENABLE + struct ether_addr ea_addr; + #endif /* GET_CUSTOM_MAC_ENABLE */ +- + #ifdef DISABLE_11N + uint32 nmode = 0; ++#else ++#ifdef AMPDU_HOSTREORDER ++ uint32 hostreorder = 1; ++#endif + #endif /* DISABLE_11N */ +-#ifdef USE_WL_TXBF +- uint32 txbf = 1; +-#endif /* USE_WL_TXBF */ +-#ifdef USE_WL_FRAMEBURST +- uint32 frameburst = 1; +-#endif /* USE_WL_FRAMEBURST */ +-#ifdef SUPPORT_2G_VHT +- uint32 vht_features = 0x3; /* 2G enable | rates all */ +-#endif /* SUPPORT_2G_VHT */ ++ dhd->suspend_bcn_li_dtim = CUSTOM_SUSPEND_BCN_LI_DTIM; + #ifdef PROP_TXSTATUS + #ifdef PROP_TXSTATUS_VSDB +- /* In case the host does not support proptxstatus, hostreorder in dongle should be off */ +- uint32 hostreorder = 0; + dhd->wlfc_enabled = FALSE; + /* enable WLFC only if the firmware is VSDB */ + #else +- if (!disable_proptx) +- dhd->wlfc_enabled = TRUE; +- else +- dhd->wlfc_enabled = FALSE; ++ dhd->wlfc_enabled = TRUE; + #endif /* PROP_TXSTATUS_VSDB */ + #endif /* PROP_TXSTATUS */ +-#ifdef WLTDLS +- dhd->tdls_enable = FALSE; +-#endif /* WLTDLS */ +- dhd->suspend_bcn_li_dtim = CUSTOM_SUSPEND_BCN_LI_DTIM; + DHD_TRACE(("Enter %s\n", __FUNCTION__)); + dhd->op_mode = 0; + #ifdef GET_CUSTOM_MAC_ENABLE +@@ -3796,16 +3504,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) + #endif /* GET_CUSTOM_MAC_ENABLE */ + + DHD_TRACE(("Firmware = %s\n", fw_path)); +- /* get a capabilities from firmware */ +- memset(dhd->fw_capabilities, 0, sizeof(dhd->fw_capabilities)); +- bcm_mkiovar("cap", 0, 0, dhd->fw_capabilities, sizeof(dhd->fw_capabilities)); +- if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, dhd->fw_capabilities, +- sizeof(dhd->fw_capabilities), FALSE, 0)) < 0) { +- DHD_ERROR(("%s: Get Capability failed (error=%d)\n", +- __FUNCTION__, ret)); +- return 0; +- } +- DHD_TRACE(("Firmare Capabilities: %s\n", dhd->fw_capabilities)); ++ + if ((!op_mode && strstr(fw_path, "_apsta") != NULL) || + (op_mode == DHD_FLAG_HOSTAP_MODE)) { + #ifdef SET_RANDOM_MAC_SOFTAP +@@ -3819,8 +3518,8 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) + dhd_pkt_filter_enable = FALSE; + #endif + #ifdef SET_RANDOM_MAC_SOFTAP +- SRANDOM32((uint)jiffies); +- rand_mac = RANDOM32(); ++ srandom32((uint)jiffies); ++ rand_mac = random32(); + iovbuf[0] = 0x02; /* locally administered bit */ + iovbuf[1] = 0x1A; + iovbuf[2] = 0x11; +@@ -3843,6 +3542,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) + DHD_ERROR(("%s mpc for HostAPD failed %d\n", __FUNCTION__, ret)); + } + #endif ++ + } + else { + uint32 concurrent_mode = 0; +@@ -3855,15 +3555,11 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) + dhd_pkt_filter_enable = FALSE; + #endif + dhd->op_mode = DHD_FLAG_P2P_MODE; +- } else if (op_mode == DHD_FLAG_IBSS_MODE || +- (!op_mode && strstr(fw_path, "_ibss") != NULL)) { +- dhd->op_mode = DHD_FLAG_IBSS_MODE; +- } else { +- dhd->op_mode = DHD_FLAG_STA_MODE; + } ++ else ++ dhd->op_mode = DHD_FLAG_STA_MODE; + #if !defined(AP) && defined(WLP2P) +- if (dhd->op_mode != DHD_FLAG_IBSS_MODE && +- (concurrent_mode = dhd_get_concurrent_capabilites(dhd))) { ++ if ((concurrent_mode = dhd_get_concurrent_capabilites(dhd))) { + #if defined(ARP_OFFLOAD_SUPPORT) + arpoe = 1; + #endif +@@ -3916,7 +3612,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) + bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf)); + dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); + #endif /* ROAM_ENABLE || DISABLE_BUILTIN_ROAM */ +-#if defined(ROAM_ENABLE) ++#ifdef ROAM_ENABLE + if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_ROAM_TRIGGER, roam_trigger, + sizeof(roam_trigger), TRUE, 0)) < 0) + DHD_ERROR(("%s: roam trigger set failed %d\n", __FUNCTION__, ret)); +@@ -3929,24 +3625,8 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) + bcm_mkiovar("fullroamperiod", (char *)&roam_fullscan_period, 4, iovbuf, sizeof(iovbuf)); + if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) + DHD_ERROR(("%s: roam fullscan period set failed %d\n", __FUNCTION__, ret)); +-#ifdef ROAM_AP_ENV_DETECTION +- if (roam_trigger[0] == WL_AUTO_ROAM_TRIGGER) { +- bcm_mkiovar("roam_env_detection", (char *)&roam_env_mode, +- 4, iovbuf, sizeof(iovbuf)); +- if (dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0) == BCME_OK) +- dhd->roam_env_detection = TRUE; +- else { +- dhd->roam_env_detection = FALSE; +- } +- } +-#endif /* ROAM_AP_ENV_DETECTION */ + #endif /* ROAM_ENABLE */ + +-#ifdef WLTDLS +- /* by default TDLS on and auto mode off */ +- _dhd_tdls_enable(dhd, true, false, NULL); +-#endif /* WLTDLS */ +- + /* Set PowerSave mode */ + dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, sizeof(power_mode), TRUE, 0); + +@@ -3974,6 +3654,11 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) + dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); + #endif /* defined(AP) && !defined(WLP2P) */ + ++ if (dhd_bus_chip_id(dhd) == BCM43341_CHIP_ID || dhd_bus_chip_id(dhd) == BCM4324_CHIP_ID) { ++ /* Turn on HT40 in 2.4 GHz */ ++ bcm_mkiovar("mimo_bw_cap", (char *)&mimo_bw_cap, 4, iovbuf, sizeof(iovbuf)); ++ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); ++ } + + #if defined(SOFTAP) + if (ap_fw_loaded == TRUE) { +@@ -3996,41 +3681,6 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) + } + } + #endif /* defined(KEEP_ALIVE) */ +-#ifdef USE_WL_TXBF +- bcm_mkiovar("txbf", (char *)&txbf, 4, iovbuf, sizeof(iovbuf)); +- if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, +- sizeof(iovbuf), TRUE, 0)) < 0) { +- DHD_ERROR(("%s Set txbf failed %d\n", __FUNCTION__, ret)); +- } +-#endif /* USE_WL_TXBF */ +-#ifdef USE_WL_FRAMEBURST +- /* Set frameburst to value */ +- if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_FAKEFRAG, (char *)&frameburst, +- sizeof(frameburst), TRUE, 0)) < 0) { +- DHD_ERROR(("%s Set frameburst failed %d\n", __FUNCTION__, ret)); +- } +-#endif /* USE_WL_FRAMEBURST */ +-#ifdef CUSTOM_AMPDU_BA_WSIZE +- /* Set ampdu ba wsize to 64 */ +- bcm_mkiovar("ampdu_ba_wsize", (char *)&du_ba_wsize, 4, iovbuf, sizeof(iovbuf)); +- if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, +- sizeof(iovbuf), TRUE, 0)) < 0) { +- DHD_ERROR(("%s Set ampdu_ba_wsize to %d failed %d\n", +- __FUNCTION__, CUSTOM_AMPDU_BA_WSIZE, ret)); +- } +-#endif /* CUSTOM_AMPDU_BA_WSIZE */ +-#ifdef SUPPORT_2G_VHT +- bcm_mkiovar("vht_features", (char *)&vht_features, 4, iovbuf, sizeof(iovbuf)); +- if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) { +- DHD_ERROR(("%s vht_features set failed %d\n", __FUNCTION__, ret)); +- } +-#endif /* SUPPORT_2G_VHT */ +- +- bcm_mkiovar("buf_key_b4_m4", (char *)&buf_key_b4_m4, 4, iovbuf, sizeof(iovbuf)); +- if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, +- sizeof(iovbuf), TRUE, 0)) < 0) { +- DHD_ERROR(("%s buf_key_b4_m4 set failed %d\n", __FUNCTION__, ret)); +- } + + /* Read event_msgs mask */ + bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf)); +@@ -4052,7 +3702,6 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) + setbit(eventmask, WLC_E_DISASSOC_IND); + setbit(eventmask, WLC_E_DISASSOC); + setbit(eventmask, WLC_E_JOIN); +- setbit(eventmask, WLC_E_START); + setbit(eventmask, WLC_E_ASSOC_IND); + setbit(eventmask, WLC_E_PSK_SUP); + setbit(eventmask, WLC_E_LINK); +@@ -4071,15 +3720,9 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) + #endif /* WLMEDIA_HTSF */ + #ifdef PNO_SUPPORT + setbit(eventmask, WLC_E_PFN_NET_FOUND); +- setbit(eventmask, WLC_E_PFN_BEST_BATCHING); +- setbit(eventmask, WLC_E_PFN_BSSID_NET_FOUND); +- setbit(eventmask, WLC_E_PFN_BSSID_NET_LOST); + #endif /* PNO_SUPPORT */ + /* enable dongle roaming event */ + setbit(eventmask, WLC_E_ROAM); +-#ifdef WLTDLS +- setbit(eventmask, WLC_E_TDLS_PEER_EVENT); +-#endif /* WLTDLS */ + #ifdef WL_CFG80211 + setbit(eventmask, WLC_E_ESCAN_RESULT); + if (dhd->op_mode & DHD_FLAG_P2P_MODE) { +@@ -4120,36 +3763,46 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) + + #ifdef PKT_FILTER_SUPPORT + /* Setup default defintions for pktfilter , enable in suspend */ +- dhd->pktfilter_count = 6; ++ dhd->pktfilter_count = 5; + /* Setup filter to allow only unicast */ +- dhd->pktfilter[DHD_UNICAST_FILTER_NUM] = "100 0 0 0 0x01 0x00"; +- dhd->pktfilter[DHD_BROADCAST_FILTER_NUM] = NULL; +- dhd->pktfilter[DHD_MULTICAST4_FILTER_NUM] = NULL; +- dhd->pktfilter[DHD_MULTICAST6_FILTER_NUM] = NULL; ++ dhd->pktfilter[0] = "100 0 0 0 0x01 0x00"; ++ dhd->pktfilter[1] = NULL; ++ dhd->pktfilter[2] = NULL; ++ dhd->pktfilter[3] = NULL; + /* Add filter to pass multicastDNS packet and NOT filter out as Broadcast */ +- dhd->pktfilter[DHD_MDNS_FILTER_NUM] = "104 0 0 0 0xFFFFFFFFFFFF 0x01005E0000FB"; +- /* apply APP pktfilter */ +- dhd->pktfilter[DHD_ARP_FILTER_NUM] = "105 0 0 12 0xFFFF 0x0806"; ++ dhd->pktfilter[4] = "104 0 0 0 0xFFFFFFFFFFFF 0x01005E0000FB"; ++ dhd_set_packet_filter(dhd); + + #if defined(SOFTAP) + if (ap_fw_loaded) { + dhd_enable_packet_filter(0, dhd); + } + #endif /* defined(SOFTAP) */ +- dhd_set_packet_filter(dhd); ++ + #endif /* PKT_FILTER_SUPPORT */ + #ifdef DISABLE_11N + bcm_mkiovar("nmode", (char *)&nmode, 4, iovbuf, sizeof(iovbuf)); + if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) + DHD_ERROR(("%s wl nmode 0 failed %d\n", __FUNCTION__, ret)); + #else +-#if defined(PROP_TXSTATUS) && defined(PROP_TXSTATUS_VSDB) ++#ifdef AMPDU_HOSTREORDER + bcm_mkiovar("ampdu_hostreorder", (char *)&hostreorder, 4, buf, sizeof(buf)); + dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, sizeof(buf), TRUE, 0); +-#endif ++#endif /* AMPDU_HOSTREORDER */ + #endif /* DISABLE_11N */ + ++#if !defined(WL_CFG80211) ++ /* Force STA UP */ ++ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_UP, (char *)&up, sizeof(up), TRUE, 0)) < 0) { ++ DHD_ERROR(("%s Setting WL UP failed %d\n", __FUNCTION__, ret)); ++ goto done; ++ } ++#endif + ++#ifdef ENABLE_BCN_LI_BCN_WAKEUP ++ bcm_mkiovar("bcn_li_bcn", (char *)&bcn_li_bcn, 4, iovbuf, sizeof(iovbuf)); ++ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); ++#endif /* ENABLE_BCN_LI_BCN_WAKEUP */ + + /* query for 'ver' to get version info from firmware */ + memset(buf, 0, sizeof(buf)); +@@ -4161,8 +3814,12 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) + bcmstrtok(&ptr, "\n", 0); + /* Print fw version info */ + DHD_ERROR(("Firmware version = %s\n", buf)); ++ + dhd_set_version_info(dhd, buf); + ++ DHD_BLOG(buf, strlen(buf) + 1); ++ DHD_BLOG(dhd_version, strlen(dhd_version) + 1); ++ + /* Check and adjust IOCTL response timeout for Manufactring firmware */ + if (strstr(buf, MANUFACTRING_FW) != NULL) { + dhd_os_set_ioctl_resp_timeout(20000); +@@ -4171,21 +3828,6 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) + } + } + +-#ifdef BCMSDIOH_TXGLOM +- if (bcmsdh_glom_enabled()) { +- dhd_txglom_enable(dhd, TRUE); +- } +-#endif /* BCMSDIOH_TXGLOM */ +- +-#if defined(PROP_TXSTATUS) && !defined(PROP_TXSTATUS_VSDB) +- dhd_wlfc_init(dhd); +-#endif /* PROP_TXSTATUS && !PROP_TXSTATUS_VSDB */ +-#ifdef PNO_SUPPORT +- if (!dhd->pno_state) { +- dhd_pno_init(dhd); +- } +-#endif +- + done: + return ret; + } +@@ -4206,7 +3848,7 @@ dhd_iovar(dhd_pub_t *pub, int ifidx, cha + ioc.cmd = set? WLC_SET_VAR : WLC_GET_VAR; + ioc.buf = buf; + ioc.len = len; +- ioc.set = set; ++ ioc.set = TRUE; + + ret = dhd_wl_ioctl(pub, ifidx, &ioc, ioc.buf, ioc.len); + if (!set && ret >= 0) +@@ -4317,9 +3959,9 @@ static int dhd_device_event(struct notif + /* Filter notifications meant for non Broadcom devices */ + if ((ifa->ifa_dev->dev->netdev_ops != &dhd_ops_pri) && + (ifa->ifa_dev->dev->netdev_ops != &dhd_ops_virt)) { +-#if defined(WL_ENABLE_P2P_IF) ++#ifdef WLP2P + if (!wl_cfgp2p_is_ifops(ifa->ifa_dev->dev->netdev_ops)) +-#endif /* WL_ENABLE_P2P_IF */ ++#endif + return NOTIFY_DONE; + } + #endif /* LINUX_VERSION_CODE */ +@@ -4362,99 +4004,35 @@ static int dhd_device_event(struct notif + break; + } + +-#ifdef AOE_IP_ALIAS_SUPPORT +- DHD_ARPOE(("%s:add aliased IP to AOE hostip cache\n", +- __FUNCTION__)); +- aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, TRUE, idx); +-#endif /* AOE_IP_ALIAS_SUPPORT */ +- break; +- +- case NETDEV_DOWN: +- DHD_ARPOE(("%s: [%s] Down IP: 0x%x\n", +- __FUNCTION__, ifa->ifa_label, ifa->ifa_address)); +- dhd->pend_ipaddr = 0; +-#ifdef AOE_IP_ALIAS_SUPPORT +- DHD_ARPOE(("%s:interface is down, AOE clr all for this if\n", +- __FUNCTION__)); +- aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, FALSE, idx); +-#else +- dhd_aoe_hostip_clr(&dhd->pub, idx); +- dhd_aoe_arp_clr(&dhd->pub, idx); +-#endif /* AOE_IP_ALIAS_SUPPORT */ +- break; +- +- default: +- DHD_ARPOE(("%s: do noting for [%s] Event: %lu\n", +- __func__, ifa->ifa_label, event)); +- break; +- } +- return NOTIFY_DONE; +-} +-#endif /* ARP_OFFLOAD_SUPPORT */ +- +-/* +- * Neighbor Discovery Offload: Called when an interface +- * is assigned with ipv6 address. +- * Handles only primary interface +- */ +-static int dhd_device_ipv6_event(struct notifier_block *this, +- unsigned long event, +- void *ptr) +-{ +- dhd_info_t *dhd; +- dhd_pub_t *dhd_pub; +- struct ipv6_addr *_ipv6_addr = NULL; +- struct inet6_ifaddr *inet6_ifa = ptr; +- int idx = 0; +- +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) +- /* Filter notifications meant for non Broadcom devices */ +- if (inet6_ifa->idev->dev->netdev_ops != &dhd_ops_pri) { +- goto exit; +- } +-#endif /* LINUX_VERSION_CODE */ +- +- dhd = *(dhd_info_t **)netdev_priv(inet6_ifa->idev->dev); +- if (!dhd) +- goto exit; +- +- idx = dhd_net2idx(dhd, inet6_ifa->idev->dev); +- if (idx == DHD_BAD_IF) { +- DHD_ERROR(("Cannot find ifidx")); +- goto exit; +- } +- dhd_pub = &dhd->pub; +- if (!FW_SUPPORTED(dhd_pub, ndoe)) +- goto exit; +- if (event == NETDEV_UP || event == NETDEV_DOWN) { +- _ipv6_addr = NATIVE_MALLOC(dhd_pub->osh, sizeof(struct ipv6_addr)); +- if (_ipv6_addr == NULL) { +- DHD_ERROR(("Failed to allocate ipv6\n")); +- goto exit; +- } +- memcpy(&_ipv6_addr->ipv6_addr[0], &inet6_ifa->addr, IPV6_ADDR_LEN); +- DHD_TRACE(("IPV6 address : %pI6\n", &inet6_ifa->addr)); +- } +- switch (event) { +- case NETDEV_UP: +- DHD_TRACE(("%s: Enable NDO and add ipv6 into table \n ", __FUNCTION__)); +- _ipv6_addr->ipv6_oper = DHD_IPV6_ADDR_ADD; ++#ifdef AOE_IP_ALIAS_SUPPORT ++ DHD_ARPOE(("%s:add aliased IP to AOE hostip cache\n", ++ __FUNCTION__)); ++ aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, TRUE, idx); ++#endif + break; ++ + case NETDEV_DOWN: +- DHD_TRACE(("%s: clear ipv6 table \n", __FUNCTION__)); +- _ipv6_addr->ipv6_oper = DHD_IPV6_ADDR_DELETE; ++ DHD_ARPOE(("%s: [%s] Down IP: 0x%x\n", ++ __FUNCTION__, ifa->ifa_label, ifa->ifa_address)); ++ dhd->pend_ipaddr = 0; ++#ifdef AOE_IP_ALIAS_SUPPORT ++ DHD_ARPOE(("%s:interface is down, AOE clr all for this if\n", ++ __FUNCTION__)); ++ aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, FALSE, idx); ++#else ++ dhd_aoe_hostip_clr(&dhd->pub, idx); ++ dhd_aoe_arp_clr(&dhd->pub, idx); ++#endif /* AOE_IP_ALIAS_SUPPORT */ + break; ++ + default: +- DHD_ERROR(("%s: unknown notifier event \n", __FUNCTION__)); +- goto exit; ++ DHD_ARPOE(("%s: do noting for [%s] Event: %lu\n", ++ __func__, ifa->ifa_label, event)); ++ break; + } +- spin_lock_bh(&dhd->iflist[idx]->ipv6_lock); +- list_add_tail(&_ipv6_addr->list, &dhd->iflist[idx]->ipv6_list); +- spin_unlock_bh(&dhd->iflist[idx]->ipv6_lock); +- up(&dhd->thr_sysioc_ctl.sema); +-exit: + return NOTIFY_DONE; + } ++#endif /* ARP_OFFLOAD_SUPPORT */ + + int + dhd_net_attach(dhd_pub_t *dhdp, int ifidx) +@@ -4520,20 +4098,19 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifid + net->ethtool_ops = &dhd_ethtool_ops; + #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */ + +-#if defined(WL_WIRELESS_EXT) ++#if defined(CONFIG_WIRELESS_EXT) + #if WIRELESS_EXT < 19 + net->get_wireless_stats = dhd_get_wireless_stats; + #endif /* WIRELESS_EXT < 19 */ + #if WIRELESS_EXT > 12 + net->wireless_handlers = (struct iw_handler_def *)&wl_iw_handler_def; + #endif /* WIRELESS_EXT > 12 */ +-#endif /* defined(WL_WIRELESS_EXT) */ ++#endif /* defined(CONFIG_WIRELESS_EXT) */ + + dhd->pub.rxsz = DBUS_RX_BUFFER_SIZE_DHD(net); + + memcpy(net->dev_addr, temp_addr, ETHER_ADDR_LEN); + +- net->ifindex = 0; + if ((err = register_netdev(net)) != 0) { + DHD_ERROR(("couldn't register the net device, err %d\n", err)); + goto fail; +@@ -4543,11 +4120,11 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifid + net->name, + MAC2STRDBG(net->dev_addr)); + +-#if defined(SOFTAP) && defined(WL_WIRELESS_EXT) && !defined(WL_CFG80211) ++#if defined(SOFTAP) && defined(CONFIG_WIRELESS_EXT) && !defined(WL_CFG80211) + wl_iw_iscan_set_scan_broadcast_prep(net, 1); + #endif + +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) ++#if 1 && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) + if (ifidx == 0) { + dhd_registration_check = TRUE; + up(&dhd_registration_sem); +@@ -4609,19 +4186,13 @@ void dhd_detach(dhd_pub_t *dhdp) + return; + + DHD_TRACE(("%s: Enter state 0x%x\n", __FUNCTION__, dhd->dhd_state)); +-#ifdef ARP_OFFLOAD_SUPPORT +- unregister_inetaddr_notifier(&dhd_notifier); +-#endif /* ARP_OFFLOAD_SUPPORT */ +-#ifdef IPV6 +- unregister_inet6addr_notifier(&dhd_notifier_ipv6); +-#endif + + dhd->pub.up = 0; + if (!(dhd->dhd_state & DHD_ATTACH_STATE_DONE)) { + /* Give sufficient time for threads to start running in case + * dhd_attach() has failed + */ +- OSL_SLEEP(100); ++ osl_delay(1000*100); + } + + if (dhd->dhd_state & DHD_ATTACH_STATE_PROT_ATTACH) { +@@ -4630,23 +4201,28 @@ void dhd_detach(dhd_pub_t *dhdp) + if (dhdp->prot) + dhd_prot_detach(dhdp); + } ++ ++#ifdef ARP_OFFLOAD_SUPPORT ++ unregister_inetaddr_notifier(&dhd_notifier); ++#endif /* ARP_OFFLOAD_SUPPORT */ ++ + #if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) + if (dhd->dhd_state & DHD_ATTACH_STATE_EARLYSUSPEND_DONE) { + if (dhd->early_suspend.suspend) + unregister_early_suspend(&dhd->early_suspend); + } +-#endif /* CONFIG_HAS_EARLYSUSPEND && DHD_USE_EARLYSUSPEND */ ++#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */ + + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) + cancel_work_sync(&dhd->work_hang); + #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ + +-#if defined(WL_WIRELESS_EXT) ++#if defined(CONFIG_WIRELESS_EXT) + if (dhd->dhd_state & DHD_ATTACH_STATE_WL_ATTACH) { + /* Detatch and unlink in the iw */ + wl_iw_detach(); + } +-#endif /* defined(WL_WIRELESS_EXT) */ ++#endif /* defined(CONFIG_WIRELESS_EXT) */ + + if (dhd->thr_sysioc_ctl.thr_pid >= 0) { + PROC_STOP(&dhd->thr_sysioc_ctl); +@@ -4705,15 +4281,11 @@ void dhd_detach(dhd_pub_t *dhdp) + if (dhd->thr_dpc_ctl.thr_pid >= 0) { + PROC_STOP(&dhd->thr_dpc_ctl); + } +-#ifdef RXFRAME_THREAD +- if (dhd->thr_rxf_ctl.thr_pid >= 0) { +- PROC_STOP(&dhd->thr_rxf_ctl); +- } +-#endif + else + #endif /* DHDTHREAD */ + tasklet_kill(&dhd->tasklet); + } ++ + #ifdef WL_CFG80211 + if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) { + wl_cfg80211_detach(NULL); +@@ -4721,26 +4293,38 @@ void dhd_detach(dhd_pub_t *dhdp) + } + #endif + +-#ifdef PNO_SUPPORT +- if (dhdp->pno_state) +- dhd_pno_deinit(dhdp); +-#endif +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && (LINUX_VERSION_CODE <= \ +- KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM_SLEEP) ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) + unregister_pm_notifier(&dhd_sleep_pm_notifier); +-#endif /* (LINUX_VERSION >= 2.6.27 && LINUX_VERSION <= 2.6.39 && CONFIG_PM_SLEEP */ ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */ ++ /* && defined(CONFIG_PM_SLEEP) */ + + if (dhd->dhd_state & DHD_ATTACH_STATE_WAKELOCKS_INIT) { +- DHD_TRACE(("wd wakelock count:%d\n", dhd->wakelock_wd_counter)); + #ifdef CONFIG_HAS_WAKELOCK + dhd->wakelock_counter = 0; + dhd->wakelock_wd_counter = 0; + dhd->wakelock_rx_timeout_enable = 0; + dhd->wakelock_ctrl_timeout_enable = 0; +- wake_lock_destroy(&dhd->wl_wifi); +- wake_lock_destroy(&dhd->wl_rxwake); +- wake_lock_destroy(&dhd->wl_ctrlwake); +- wake_lock_destroy(&dhd->wl_wdwake); ++ if (dhd->wl_wifi) { ++ wake_lock_destroy(dhd->wl_wifi); ++ MFREE(dhd->pub.osh, dhd->wl_wifi, sizeof(struct wake_lock)); ++ dhd->wl_wifi = NULL; ++ } ++ if (dhd->wl_rxwake) { ++ wake_lock_destroy(dhd->wl_rxwake); ++ MFREE(dhd->pub.osh, dhd->wl_rxwake, sizeof(struct wake_lock)); ++ dhd->wl_rxwake = NULL; ++ } ++ if (dhd->wl_ctrlwake) { ++ wake_lock_destroy(dhd->wl_ctrlwake); ++ MFREE(dhd->pub.osh, dhd->wl_ctrlwake, sizeof(struct wake_lock)); ++ dhd->wl_ctrlwake = NULL; ++ } ++ if (dhd->wl_wdwake) { ++ wake_lock_destroy(dhd->wl_wdwake); ++ MFREE(dhd->pub.osh, dhd->wl_wdwake, sizeof(struct wake_lock)); ++ dhd->wl_wdwake = NULL; ++ } + #endif /* CONFIG_HAS_WAKELOCK */ + } + } +@@ -4770,19 +4354,8 @@ dhd_free(dhd_pub_t *dhdp) + } + } + dhd = (dhd_info_t *)dhdp->info; +-#if defined(CONFIG_DHD_USE_STATIC_BUF) +- /* If pointer is allocated by dhd_os_prealloc then avoid MFREE */ +- if (dhd != (dhd_info_t *)dhd_os_prealloc(NULL, DHD_PREALLOC_DHD_INFO, 0)) { +-#endif /* CONFIG_DHD_USE_STATIC_BUF */ +- if (dhd) +- MFREE(dhd->pub.osh, dhd, sizeof(*dhd)); +-#if defined(CONFIG_DHD_USE_STATIC_BUF) +- } +- else { +- if (dhd) +- dhd = NULL; +- } +-#endif /* CONFIG_DHD_USE_STATIC_BUF */ ++ if (dhd) ++ MFREE(dhd->pub.osh, dhd, sizeof(*dhd)); + } + } + +@@ -4800,25 +4373,35 @@ dhd_module_cleanup(void) + + /* Call customer gpio to turn off power with WL_REG_ON signal */ + dhd_customer_gpio_wlan_ctrl(WLAN_POWER_OFF); +-} + ++ if (wl_host_wake > 0) ++ gpio_free(wl_host_wake); ++ wl_host_wake = -1; ++} + +-#if defined(CONFIG_WIFI_CONTROL_FUNC) +-extern bool g_wifi_poweron; +-#endif /* CONFIG_WIFI_CONTROL_FUNC */ + + static int __init + dhd_module_init(void) + { + int error = 0; + +-#if defined(BCMLXSDMMC) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) ++#if 1 && defined(BCMLXSDMMC) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) + int retry = POWERUP_MAX_RETRY; + int chip_up = 0; + #endif + + DHD_TRACE(("%s: Enter\n", __FUNCTION__)); + ++ if (gpio_request(WL_HOST_WAKE_DEF_GPIO, "wl_host_wake")) { ++ pr_warning("[%s] get wl_host_wake gpio failed\n", __FUNCTION__); ++ wl_host_wake = -1; ++ return -1; ++ } ++ wl_host_wake = WL_HOST_WAKE_DEF_GPIO; ++ gpio_direction_input(wl_host_wake); ++ wl_host_wake_irqno = gpio_to_irq(wl_host_wake); ++ pr_info("bcmdhd: got gpio%d, mapped to irqno%d\n", wl_host_wake, wl_host_wake_irqno); ++ + wl_android_init(); + + #if defined(DHDTHREAD) +@@ -4833,13 +4416,11 @@ dhd_module_init(void) + break; + + DHD_ERROR(("Invalid module parameters.\n")); +- error = -EINVAL; ++ return -EINVAL; + } while (0); + #endif +- if (error) +- goto fail_0; + +-#if defined(BCMLXSDMMC) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) ++#if 1 && defined(BCMLXSDMMC) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) + do { + sema_init(&dhd_chipup_sem, 0); + dhd_bus_reg_sdio_notify(&dhd_chipup_sem); +@@ -4867,8 +4448,7 @@ dhd_module_init(void) + + if (!chip_up) { + DHD_ERROR(("\nfailed to power up wifi chip, max retry reached, exits **\n\n")); +- error = -ENODEV; +- goto fail_0; ++ return -ENODEV; + } + #else + dhd_customer_gpio_wlan_ctrl(WLAN_POWER_ON); +@@ -4879,18 +4459,7 @@ dhd_module_init(void) + + #endif + +-#if defined(CONFIG_WIFI_CONTROL_FUNC) && defined(BCMLXSDMMC) +- /* If the wifi_set_power() is failed, +- * we need to jump error handling routines. +- */ +- if (!g_wifi_poweron) { +- printk("%s: wifi_set_power() failed\n", __FUNCTION__); +- error = -ENODEV; +- goto fail_1; +- } +-#endif /* defined(CONFIG_WIFI_CONTROL_FUNC) */ +- +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) ++#if 1 && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) + sema_init(&dhd_registration_sem, 0); + #endif + +@@ -4904,7 +4473,7 @@ dhd_module_init(void) + goto fail_1; + } + +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(BCMLXSDMMC) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) + /* + * Wait till MMC sdio_register_driver callback called and made driver attach. + * It's needed to make sync up exit from dhd insmod and +@@ -4924,7 +4493,7 @@ dhd_module_init(void) + + return error; + +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(BCMLXSDMMC) ++#if 1 && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) + fail_2: + dhd_bus_unregister(); + #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ +@@ -4938,21 +4507,14 @@ fail_1: + /* Call customer gpio to turn off power with WL_REG_ON signal */ + dhd_customer_gpio_wlan_ctrl(WLAN_POWER_OFF); + +-fail_0: +- wl_android_exit(); +- + return error; + } + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) +-#ifdef USE_LATE_INITCALL_SYNC +-late_initcall_sync(dhd_module_init); +-#else + late_initcall(dhd_module_init); +-#endif /* USE_LATE_INITCALL_SYNC */ + #else + module_init(dhd_module_init); +-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) */ ++#endif + + module_exit(dhd_module_cleanup); + +@@ -5027,19 +4589,6 @@ dhd_os_ioctl_resp_wake(dhd_pub_t *pub) + } + + void +-dhd_os_wd_timer_extend(void *bus, bool extend) +-{ +- dhd_pub_t *pub = bus; +- dhd_info_t *dhd = (dhd_info_t *)pub->info; +- +- if (extend) +- dhd_os_wd_timer(bus, WATCHDOG_EXTEND_INTERVAL); +- else +- dhd_os_wd_timer(bus, dhd->default_wd_interval); +-} +- +- +-void + dhd_os_wd_timer(void *bus, uint wdtick) + { + dhd_pub_t *pub = bus; +@@ -5048,22 +4597,21 @@ dhd_os_wd_timer(void *bus, uint wdtick) + + DHD_TRACE(("%s: Enter\n", __FUNCTION__)); + +- if (!dhd) { +- DHD_ERROR(("%s: dhd NULL\n", __FUNCTION__)); ++ if (!dhd) + return; +- } ++ if (wdtick) ++ DHD_OS_WD_WAKE_LOCK(pub); + + flags = dhd_os_spin_lock(pub); + + /* don't start the wd until fw is loaded */ + if (pub->busstate == DHD_BUS_DOWN) { + dhd_os_spin_unlock(pub, flags); +- if (!wdtick) +- DHD_OS_WD_WAKE_UNLOCK(pub); ++ DHD_OS_WD_WAKE_UNLOCK(pub); + return; + } + +- /* Totally stop the timer */ ++ /* totally stop the timer */ + if (!wdtick && dhd->wd_timer_valid == TRUE) { + dhd->wd_timer_valid = FALSE; + dhd_os_spin_unlock(pub, flags); +@@ -5072,12 +4620,12 @@ dhd_os_wd_timer(void *bus, uint wdtick) + #else + del_timer(&dhd->timer); + #endif /* DHDTHREAD */ ++ /* Unlock when timer deleted */ + DHD_OS_WD_WAKE_UNLOCK(pub); + return; + } + + if (wdtick) { +- DHD_OS_WD_WAKE_LOCK(pub); + dhd_watchdog_ms = (uint)wdtick; + /* Re arm the timer, at last watchdog period */ + mod_timer(&dhd->timer, jiffies + msecs_to_jiffies(dhd_watchdog_ms)); +@@ -5198,48 +4746,6 @@ dhd_os_sdtxunlock(dhd_pub_t *pub) + dhd_os_sdunlock(pub); + } + +-#if defined(DHDTHREAD) && defined(RXFRAME_THREAD) +-static void +-dhd_os_rxflock(dhd_pub_t *pub) +-{ +- dhd_info_t *dhd; +- +- dhd = (dhd_info_t *)(pub->info); +- spin_lock_bh(&dhd->rxf_lock); +- +-} +- +-static void +-dhd_os_rxfunlock(dhd_pub_t *pub) +-{ +- dhd_info_t *dhd; +- +- dhd = (dhd_info_t *)(pub->info); +- spin_unlock_bh(&dhd->rxf_lock); +-} +-#endif /* defined(DHDTHREAD) && defined(RXFRAME_THREAD) */ +- +-#ifdef DHDTCPACK_SUPPRESS +-void +-dhd_os_tcpacklock(dhd_pub_t *pub) +-{ +- dhd_info_t *dhd; +- +- dhd = (dhd_info_t *)(pub->info); +- spin_lock_bh(&dhd->tcpack_lock); +- +-} +- +-void +-dhd_os_tcpackunlock(dhd_pub_t *pub) +-{ +- dhd_info_t *dhd; +- +- dhd = (dhd_info_t *)(pub->info); +- spin_unlock_bh(&dhd->tcpack_lock); +-} +-#endif /* DHDTCPACK_SUPPRESS */ +- + #if defined(CONFIG_DHD_USE_STATIC_BUF) + uint8* dhd_os_prealloc(void *osh, int section, uint size) + { +@@ -5251,7 +4757,7 @@ void dhd_os_prefree(void *osh, void *add + } + #endif /* defined(CONFIG_WIFI_CONTROL_FUNC) */ + +-#if defined(WL_WIRELESS_EXT) ++#if defined(CONFIG_WIRELESS_EXT) + struct iw_statistics * + dhd_get_wireless_stats(struct net_device *dev) + { +@@ -5269,7 +4775,7 @@ dhd_get_wireless_stats(struct net_device + else + return NULL; + } +-#endif /* defined(WL_WIRELESS_EXT) */ ++#endif /* defined(CONFIG_WIRELESS_EXT) */ + + static int + dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata, +@@ -5282,7 +4788,7 @@ dhd_wl_host_event(dhd_info_t *dhd, int * + if (bcmerror != BCME_OK) + return (bcmerror); + +-#if defined(WL_WIRELESS_EXT) ++#if defined(CONFIG_WIRELESS_EXT) + if (event->bsscfgidx == 0) { + /* + * Wireless ext is on primary interface only +@@ -5295,7 +4801,7 @@ dhd_wl_host_event(dhd_info_t *dhd, int * + wl_iw_event(dhd->iflist[*ifidx]->net, event, *data); + } + } +-#endif /* defined(WL_WIRELESS_EXT) */ ++#endif /* defined(CONFIG_WIRELESS_EXT) */ + + #ifdef WL_CFG80211 + if ((ntoh32(event->event_type) == WLC_E_IF) && +@@ -5329,6 +4835,103 @@ void + dhd_sendup_event(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data) + { + switch (ntoh32(event->event_type)) { ++#ifdef WLBTAMP ++ /* Send up locally generated AMP HCI Events */ ++ case WLC_E_BTA_HCI_EVENT: { ++ struct sk_buff *p, *skb; ++ bcm_event_t *msg; ++ wl_event_msg_t *p_bcm_event; ++ char *ptr; ++ uint32 len; ++ uint32 pktlen; ++ dhd_if_t *ifp; ++ dhd_info_t *dhd; ++ uchar *eth; ++ int ifidx; ++ ++ len = ntoh32(event->datalen); ++ pktlen = sizeof(bcm_event_t) + len + 2; ++ dhd = dhdp->info; ++ ifidx = dhd_ifname2idx(dhd, event->ifname); ++ ++ if ((p = PKTGET(dhdp->osh, pktlen, FALSE))) { ++ ASSERT(ISALIGNED((uintptr)PKTDATA(dhdp->osh, p), sizeof(uint32))); ++ ++ msg = (bcm_event_t *) PKTDATA(dhdp->osh, p); ++ ++ bcopy(&dhdp->mac, &msg->eth.ether_dhost, ETHER_ADDR_LEN); ++ bcopy(&dhdp->mac, &msg->eth.ether_shost, ETHER_ADDR_LEN); ++ ETHER_TOGGLE_LOCALADDR(&msg->eth.ether_shost); ++ ++ msg->eth.ether_type = hton16(ETHER_TYPE_BRCM); ++ ++ /* BCM Vendor specific header... */ ++ msg->bcm_hdr.subtype = hton16(BCMILCP_SUBTYPE_VENDOR_LONG); ++ msg->bcm_hdr.version = BCMILCP_BCM_SUBTYPEHDR_VERSION; ++ bcopy(BRCM_OUI, &msg->bcm_hdr.oui[0], DOT11_OUI_LEN); ++ ++ /* vendor spec header length + pvt data length (private indication ++ * hdr + actual message itself) ++ */ ++ msg->bcm_hdr.length = hton16(BCMILCP_BCM_SUBTYPEHDR_MINLENGTH + ++ BCM_MSG_LEN + sizeof(wl_event_msg_t) + (uint16)len); ++ msg->bcm_hdr.usr_subtype = hton16(BCMILCP_BCM_SUBTYPE_EVENT); ++ ++ PKTSETLEN(dhdp->osh, p, (sizeof(bcm_event_t) + len + 2)); ++ ++ /* copy wl_event_msg_t into sk_buf */ ++ ++ /* pointer to wl_event_msg_t in sk_buf */ ++ p_bcm_event = &msg->event; ++ bcopy(event, p_bcm_event, sizeof(wl_event_msg_t)); ++ ++ /* copy hci event into sk_buf */ ++ bcopy(data, (p_bcm_event + 1), len); ++ ++ msg->bcm_hdr.length = hton16(sizeof(wl_event_msg_t) + ++ ntoh16(msg->bcm_hdr.length)); ++ PKTSETLEN(dhdp->osh, p, (sizeof(bcm_event_t) + len + 2)); ++ ++ ptr = (char *)(msg + 1); ++ /* Last 2 bytes of the message are 0x00 0x00 to signal that there ++ * are no ethertypes which are following this ++ */ ++ ptr[len+0] = 0x00; ++ ptr[len+1] = 0x00; ++ ++ skb = PKTTONATIVE(dhdp->osh, p); ++ 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); ++ ++ skb->data = eth; ++ skb->len = len; ++ ++ /* Strip header, count, deliver upward */ ++ skb_pull(skb, ETH_HLEN); ++ ++ /* Send the packet */ ++ if (in_interrupt()) { ++ netif_rx(skb); ++ } else { ++ netif_rx_ni(skb); ++ } ++ } ++ else { ++ /* Could not allocate a sk_buf */ ++ DHD_ERROR(("%s: unable to alloc sk_buf", __FUNCTION__)); ++ } ++ break; ++ } /* case WLC_E_BTA_HCI_EVENT */ ++#endif /* WLBTAMP */ ++ + default: + break; + } +@@ -5336,7 +4939,7 @@ dhd_sendup_event(dhd_pub_t *dhdp, wl_eve + + void dhd_wait_for_event(dhd_pub_t *dhd, bool *lockvar) + { +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) ++#if 1 && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) + struct dhd_info *dhdinfo = dhd->info; + + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) +@@ -5348,13 +4951,13 @@ void dhd_wait_for_event(dhd_pub_t *dhd, + dhd_os_sdunlock(dhd); + wait_event_timeout(dhdinfo->ctrl_wait, (*lockvar == FALSE), timeout); + dhd_os_sdlock(dhd); +-#endif ++#endif + return; + } + + void dhd_wait_event_wakeup(dhd_pub_t *dhd) + { +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) ++#if 1 && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) + struct dhd_info *dhdinfo = dhd->info; + if (waitqueue_active(&dhdinfo->ctrl_wait)) + wake_up(&dhdinfo->ctrl_wait); +@@ -5374,15 +4977,6 @@ dhd_dev_reset(struct net_device *dev, ui + if (dhd_wl_ioctl_cmd(&dhd->pub, WLC_DOWN, NULL, 0, TRUE, 0) < 0) { + DHD_TRACE(("%s: wl down failed\n", __FUNCTION__)); + } +-#if defined(PROP_TXSTATUS) && !defined(PROP_TXSTATUS_VSDB) +- dhd_wlfc_deinit(&dhd->pub); +- if (dhd->pub.plat_deinit) +- dhd->pub.plat_deinit((void *)&dhd->pub); +-#endif /* PROP_TXSTATUS && !PROP_TXSTATUS_VSDB */ +-#ifdef PNO_SUPPORT +- if (dhd->pub.pno_state) +- dhd_pno_deinit(&dhd->pub); +-#endif + } + + ret = dhd_bus_devreset(&dhd->pub, flag); +@@ -5437,9 +5031,9 @@ int net_os_set_suspend_bcn_li_dtim(struc + #ifdef PKT_FILTER_SUPPORT + int net_os_rxfilter_add_remove(struct net_device *dev, int add_remove, int num) + { ++#ifndef GAN_LITE_NAT_KEEPALIVE_FILTER + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); + char *filterp = NULL; +- int filter_id = 0; + int ret = 0; + + if (!dhd || (num == DHD_UNICAST_FILTER_NUM) || +@@ -5447,32 +5041,27 @@ int net_os_rxfilter_add_remove(struct ne + return ret; + if (num >= dhd->pub.pktfilter_count) + return -EINVAL; +- switch (num) { ++ if (add_remove) { ++ switch (num) { + case DHD_BROADCAST_FILTER_NUM: + filterp = "101 0 0 0 0xFFFFFFFFFFFF 0xFFFFFFFFFFFF"; +- filter_id = 101; + break; + case DHD_MULTICAST4_FILTER_NUM: + filterp = "102 0 0 0 0xFFFFFF 0x01005E"; +- filter_id = 102; + break; + case DHD_MULTICAST6_FILTER_NUM: + filterp = "103 0 0 0 0xFFFF 0x3333"; +- filter_id = 103; + break; + default: + return -EINVAL; ++ } + } +- +- /* Add filter */ +- if (add_remove) { +- dhd->pub.pktfilter[num] = filterp; +- dhd_pktfilter_offload_set(&dhd->pub, dhd->pub.pktfilter[num]); +- } else { /* Delete filter */ +- dhd->pub.pktfilter[num] = NULL; +- /* dhd_pktfilter_offload_delete(&dhd->pub, filter_id); */ +- } ++ dhd->pub.pktfilter[num] = filterp; ++ dhd_pktfilter_offload_set(&dhd->pub, dhd->pub.pktfilter[num]); + return ret; ++#else ++ return 0; ++#endif /* GAN_LITE_NAT_KEEPALIVE_FILTER */ + } + + int dhd_os_enable_packet_filter(dhd_pub_t *dhdp, int val) +@@ -5506,84 +5095,52 @@ int + dhd_dev_init_ioctl(struct net_device *dev) + { + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); +- int ret; +- +- dhd_process_cid_mac(&dhd->pub, TRUE); +- +- if ((ret = dhd_preinit_ioctls(&dhd->pub)) < 0) +- goto done; +- +- dhd_process_cid_mac(&dhd->pub, FALSE); +- +-done: +- return ret; ++ return dhd_preinit_ioctls(&dhd->pub); + } + + #ifdef PNO_SUPPORT +-/* Linux wrapper to call common dhd_pno_stop_for_ssid */ ++/* Linux wrapper to call common dhd_pno_clean */ + int +-dhd_dev_pno_stop_for_ssid(struct net_device *dev) ++dhd_dev_pno_reset(struct net_device *dev) + { + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); + +- return (dhd_pno_stop_for_ssid(&dhd->pub)); ++ return (dhd_pno_clean(&dhd->pub)); + } + +-/* Linux wrapper to call common dhd_pno_set_for_ssid */ +-int +-dhd_dev_pno_set_for_ssid(struct net_device *dev, wlc_ssid_t* ssids_local, int nssid, +- uint16 scan_fr, int pno_repeat, int pno_freq_expo_max, uint16 *channel_list, int nchan) +-{ +- dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); +- +- return (dhd_pno_set_for_ssid(&dhd->pub, ssids_local, nssid, scan_fr, +- pno_repeat, pno_freq_expo_max, channel_list, nchan)); +-} + + /* Linux wrapper to call common dhd_pno_enable */ + int +-dhd_dev_pno_enable(struct net_device *dev, int enable) ++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, enable)); ++ return (dhd_pno_enable(&dhd->pub, pfn_enabled)); + } + +-/* Linux wrapper to call common dhd_pno_set_for_hotlist */ +-int +-dhd_dev_pno_set_for_hotlist(struct net_device *dev, wl_pfn_bssid_t *p_pfn_bssid, +- struct dhd_pno_hotlist_params *hotlist_params) +-{ +- dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); +- return (dhd_pno_set_for_hotlist(&dhd->pub, p_pfn_bssid, hotlist_params)); +-} + +-/* Linux wrapper to call common dhd_dev_pno_stop_for_batch */ ++/* Linux wrapper to call common dhd_pno_set */ + int +-dhd_dev_pno_stop_for_batch(struct net_device *dev) ++dhd_dev_pno_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nssid, ++ ushort scan_fr, int pno_repeat, int pno_freq_expo_max) + { + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); +- return (dhd_pno_stop_for_batch(&dhd->pub)); +-} + +-/* Linux wrapper to call common dhd_dev_pno_set_for_batch */ +-int +-dhd_dev_pno_set_for_batch(struct net_device *dev, struct dhd_pno_batch_params *batch_params) +-{ +- dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); +- return (dhd_pno_set_for_batch(&dhd->pub, batch_params)); ++ return (dhd_pno_set(&dhd->pub, ssids_local, nssid, scan_fr, pno_repeat, pno_freq_expo_max)); + } + +-/* Linux wrapper to call common dhd_dev_pno_get_for_batch */ ++/* Linux wrapper to get pno status */ + int +-dhd_dev_pno_get_for_batch(struct net_device *dev, char *buf, int bufsize) ++dhd_dev_get_pno_status(struct net_device *dev) + { + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); +- return (dhd_pno_get_for_batch(&dhd->pub, buf, bufsize, PNO_STATUS_NORMAL)); ++ ++ return (dhd_pno_get_status(&dhd->pub)); + } ++ + #endif /* PNO_SUPPORT */ + +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && (1) + static void dhd_hang_process(struct work_struct *work) + { + dhd_info_t *dhd; +@@ -5622,32 +5179,24 @@ int net_os_send_hang_message(struct net_ + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); + int ret = 0; + +- if (dhd) { +- /* Report FW problem when enabled */ +- if (dhd->pub.hang_report) { ++ if (dhd) + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) +- ret = dhd_os_send_hang_message(&dhd->pub); ++ ret = dhd_os_send_hang_message(&dhd->pub); + #else +- ret = wl_cfg80211_hang(dev, WLAN_REASON_UNSPECIFIED); ++ ret = wl_cfg80211_hang(dev, WLAN_REASON_UNSPECIFIED); + #endif +- } else { +- DHD_ERROR(("%s: FW HANG ignored (for testing purpose) and not sent up\n", +- __FUNCTION__)); +- /* Enforce bus down to stop any future traffic */ +- dhd->pub.busstate = DHD_BUS_DOWN; +- } +- } + return ret; + } +-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) && OEM_ANDROID */ ++#endif /* (OEM_ANDROID) */ + +-void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec, bool notify) ++void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec) + { + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); ++ + if (dhd && dhd->pub.up) { + memcpy(&dhd->pub.dhd_cspec, cspec, sizeof(wl_country_t)); + #ifdef WL_CFG80211 +- wl_update_wiphybands(NULL, notify); ++ wl_update_wiphybands(NULL, true); + #endif + } + } +@@ -5676,7 +5225,7 @@ void dhd_net_if_unlock(struct net_device + + static void dhd_net_if_lock_local(dhd_info_t *dhd) + { +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 + if (dhd) + mutex_lock(&dhd->dhd_net_if_mutex); + #endif +@@ -5684,7 +5233,7 @@ static void dhd_net_if_lock_local(dhd_in + + static void dhd_net_if_unlock_local(dhd_info_t *dhd) + { +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 + if (dhd) + mutex_unlock(&dhd->dhd_net_if_mutex); + #endif +@@ -5692,7 +5241,7 @@ static void dhd_net_if_unlock_local(dhd_ + + static void dhd_suspend_lock(dhd_pub_t *pub) + { +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 + dhd_info_t *dhd = (dhd_info_t *)(pub->info); + if (dhd) + mutex_lock(&dhd->dhd_suspend_mutex); +@@ -5701,7 +5250,7 @@ static void dhd_suspend_lock(dhd_pub_t * + + static void dhd_suspend_unlock(dhd_pub_t *pub) + { +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 + dhd_info_t *dhd = (dhd_info_t *)(pub->info); + if (dhd) + mutex_unlock(&dhd->dhd_suspend_mutex); +@@ -5733,7 +5282,7 @@ dhd_get_pend_8021x_cnt(dhd_info_t *dhd) + return (atomic_read(&dhd->pend_8021x_cnt)); + } + +-#define MAX_WAIT_FOR_8021X_TX 50 ++#define MAX_WAIT_FOR_8021X_TX 25 + + int + dhd_wait_pend8021x(struct net_device *dev) +@@ -5753,10 +5302,7 @@ dhd_wait_pend8021x(struct net_device *de + pend = dhd_get_pend_8021x_cnt(dhd); + } + if (ntimes == 0) +- { +- atomic_set(&dhd->pend_8021x_cnt, 0); + DHD_ERROR(("%s: TIMEOUT\n", __FUNCTION__)); +- } + return pend; + } + +@@ -5809,10 +5355,10 @@ int dhd_os_wake_lock_timeout(dhd_pub_t * + dhd->wakelock_rx_timeout_enable : dhd->wakelock_ctrl_timeout_enable; + #ifdef CONFIG_HAS_WAKELOCK + if (dhd->wakelock_rx_timeout_enable) +- wake_lock_timeout(&dhd->wl_rxwake, ++ wake_lock_timeout(dhd->wl_rxwake, + msecs_to_jiffies(dhd->wakelock_rx_timeout_enable)); + if (dhd->wakelock_ctrl_timeout_enable) +- wake_lock_timeout(&dhd->wl_ctrlwake, ++ wake_lock_timeout(dhd->wl_ctrlwake, + msecs_to_jiffies(dhd->wakelock_ctrl_timeout_enable)); + #endif + dhd->wakelock_rx_timeout_enable = 0; +@@ -5860,23 +5406,6 @@ int dhd_os_wake_lock_ctrl_timeout_enable + return 0; + } + +-int dhd_os_wake_lock_ctrl_timeout_cancel(dhd_pub_t *pub) +-{ +- dhd_info_t *dhd = (dhd_info_t *)(pub->info); +- unsigned long flags; +- +- if (dhd) { +- spin_lock_irqsave(&dhd->wakelock_spinlock, flags); +- dhd->wakelock_ctrl_timeout_enable = 0; +-#ifdef CONFIG_HAS_WAKELOCK +- if (wake_lock_active(&dhd->wl_ctrlwake)) +- wake_unlock(&dhd->wl_ctrlwake); +-#endif +- spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); +- } +- return 0; +-} +- + int net_os_wake_lock_rx_timeout_enable(struct net_device *dev, int val) + { + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); +@@ -5907,10 +5436,7 @@ int dhd_os_wake_lock(dhd_pub_t *pub) + spin_lock_irqsave(&dhd->wakelock_spinlock, flags); + #ifdef CONFIG_HAS_WAKELOCK + if (!dhd->wakelock_counter) +- wake_lock(&dhd->wl_wifi); +-#elif 1 && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) +- if (pm_dev) +- pm_stay_awake(pm_dev); ++ wake_lock(dhd->wl_wifi); + #endif + dhd->wakelock_counter++; + ret = dhd->wakelock_counter; +@@ -5942,10 +5468,7 @@ int dhd_os_wake_unlock(dhd_pub_t *pub) + dhd->wakelock_counter--; + #ifdef CONFIG_HAS_WAKELOCK + if (!dhd->wakelock_counter) +- wake_unlock(&dhd->wl_wifi); +-#elif 1 && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) +- if (pm_dev) +- pm_relax(pm_dev); ++ wake_unlock(dhd->wl_wifi); + #endif + ret = dhd->wakelock_counter; + } +@@ -5956,23 +5479,17 @@ int dhd_os_wake_unlock(dhd_pub_t *pub) + + int dhd_os_check_wakelock(void *dhdp) + { +-#if defined(CONFIG_HAS_WAKELOCK) || (1 && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, \ +- 36))) ++#ifdef CONFIG_HAS_WAKELOCK + dhd_pub_t *pub = (dhd_pub_t *)dhdp; + dhd_info_t *dhd; + + if (!pub) + return 0; + dhd = (dhd_info_t *)(pub->info); +-#endif /* CONFIG_HAS_WAKELOCK || BCMSDIO */ + +-#ifdef CONFIG_HAS_WAKELOCK + /* Indicate to the SD Host to avoid going to suspend if internal locks are up */ +- if (dhd && (wake_lock_active(&dhd->wl_wifi) || +- (wake_lock_active(&dhd->wl_wdwake)))) +- return 1; +-#elif 1 && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) +- if (dhd && (dhd->wakelock_counter > 0) && pm_dev) ++ if (dhd && (wake_lock_active(dhd->wl_wifi) || ++ (wake_lock_active(dhd->wl_wdwake)))) + return 1; + #endif + return 0; +@@ -5998,8 +5515,14 @@ int dhd_os_wd_wake_lock(dhd_pub_t *pub) + spin_lock_irqsave(&dhd->wakelock_spinlock, flags); + #ifdef CONFIG_HAS_WAKELOCK + /* if wakelock_wd_counter was never used : lock it at once */ +- if (!dhd->wakelock_wd_counter) +- wake_lock(&dhd->wl_wdwake); ++ if (!dhd->wakelock_wd_counter) { ++ if (dhd->wl_wdwake) ++ wake_lock(dhd->wl_wdwake); ++ else { ++ spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); ++ return 0; ++ } ++ } + #endif + dhd->wakelock_wd_counter++; + ret = dhd->wakelock_wd_counter; +@@ -6019,7 +5542,7 @@ int dhd_os_wd_wake_unlock(dhd_pub_t *pub + if (dhd->wakelock_wd_counter) { + dhd->wakelock_wd_counter = 0; + #ifdef CONFIG_HAS_WAKELOCK +- wake_unlock(&dhd->wl_wdwake); ++ wake_unlock(dhd->wl_wdwake); + #endif + } + spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); +@@ -6043,6 +5566,7 @@ void dhd_set_version_info(dhd_pub_t *dhd + + i = snprintf(info_string, sizeof(info_string), + " Driver: %s\n Firmware: %s ", EPI_VERSION_STR, fw); ++ printf("%s\n", info_string); + + if (!dhdp) + return; +@@ -6064,9 +5588,6 @@ int dhd_ioctl_entry_local(struct net_dev + } + + dhd = *(dhd_info_t **)netdev_priv(net); +- if (!dhd) +- return -EINVAL; +- + ifidx = dhd_net2idx(dhd, net); + if (ifidx == DHD_BAD_IF) { + DHD_ERROR(("%s bad ifidx\n", __FUNCTION__)); +@@ -6098,45 +5619,42 @@ extern int dhd_wlfc_FIFOcreditmap_update + int dhd_wlfc_interface_event(struct dhd_info *dhd, + ewlfc_mac_entry_action_t action, uint8 ifid, uint8 iftype, uint8* ea) + { +- if (dhd->pub.wlfc_state == NULL) ++ int status; ++ ++ dhd_os_wlfc_block(&dhd->pub); ++ if (dhd->pub.wlfc_state == NULL) { ++ dhd_os_wlfc_unblock(&dhd->pub); + return BCME_OK; ++ } + +- return dhd_wlfc_interface_entry_update(dhd->pub.wlfc_state, action, ifid, iftype, ea); ++ status = dhd_wlfc_interface_entry_update(dhd->pub.wlfc_state, action, ifid, iftype, ea); ++ dhd_os_wlfc_unblock(&dhd->pub); ++ return status; + } + + int dhd_wlfc_FIFOcreditmap_event(struct dhd_info *dhd, uint8* event_data) + { +- if (dhd->pub.wlfc_state == NULL) ++ int status; ++ ++ dhd_os_wlfc_block(&dhd->pub); ++ if (dhd->pub.wlfc_state == NULL) { ++ dhd_os_wlfc_unblock(&dhd->pub); + return BCME_OK; ++ } + +- return dhd_wlfc_FIFOcreditmap_update(dhd->pub.wlfc_state, event_data); ++ status = dhd_wlfc_FIFOcreditmap_update(dhd->pub.wlfc_state, event_data); ++ dhd_os_wlfc_unblock(&dhd->pub); ++ return status; + } + + int dhd_wlfc_event(struct dhd_info *dhd) + { +- return dhd_wlfc_enable(&dhd->pub); +-} +- +-void dhd_wlfc_plat_enable(void *dhd) +-{ +- return; +-} +- +-void dhd_wlfc_plat_deinit(void *dhd) +-{ +- return; +-} +- +-bool dhd_wlfc_skip_fc(void) +-{ +-#ifdef WL_CFG80211 +- extern struct wl_priv *wlcfg_drv_priv; ++ int status; + +- /* enable flow control in vsdb mode */ +- return !(wlcfg_drv_priv && wlcfg_drv_priv->vsdb_mode); +-#else +- return TRUE; /* skip flow control */ +-#endif /* WL_CFG80211 */ ++ dhd_os_wlfc_block(&dhd->pub); ++ status = dhd_wlfc_enable(&dhd->pub); ++ dhd_os_wlfc_unblock(&dhd->pub); ++ return status; + } + #endif /* PROP_TXSTATUS */ + +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/dhd_linux_sched.c linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_linux_sched.c +--- linux-sunxi/drivers/net/wireless/bcmdhd/dhd_linux_sched.c 2014-01-27 01:30:30.101433269 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_linux_sched.c 2014-02-15 00:43:44.792014069 +0100 +@@ -1,7 +1,7 @@ + /* + * Expose some of the kernel scheduler routines + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/dhd_pno.c linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_pno.c +--- linux-sunxi/drivers/net/wireless/bcmdhd/dhd_pno.c 2014-01-27 01:30:30.109433432 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_pno.c 2014-02-15 00:43:44.795014136 +0100 +@@ -53,12 +53,12 @@ + #define htodchanspec(i) htod16(i) + #define dtohchanspec(i) dtoh16(i) + #else +-#define htod32(i) (i) +-#define htod16(i) (i) +-#define dtoh32(i) (i) +-#define dtoh16(i) (i) +-#define htodchanspec(i) (i) +-#define dtohchanspec(i) (i) ++#define htod32(i) i ++#define htod16(i) i ++#define dtoh32(i) i ++#define dtoh16(i) i ++#define htodchanspec(i) i ++#define dtohchanspec(i) i + #endif /* IL_BIGENDINA */ + + #define NULL_CHECK(p, s, err) \ +@@ -91,9 +91,8 @@ is_dfs(uint16 channel) + else + return FALSE; + } +- +-int +-dhd_pno_clean(dhd_pub_t *dhd) ++static int ++_dhd_pno_clean(dhd_pub_t *dhd) + { + int pfn = 0; + int err; +@@ -127,9 +126,7 @@ _dhd_pno_suspend(dhd_pub_t *dhd) + dhd_pno_status_info_t *_pno_state; + NULL_CHECK(dhd, "dhd is NULL", err); + NULL_CHECK(dhd->pno_state, "pno_state is NULL", err); +- + DHD_PNO(("%s enter\n", __FUNCTION__)); +- _pno_state = PNO_GET_PNOSTATE(dhd); + err = dhd_iovar(dhd, 0, "pfn_suspend", (char *)&suspend, sizeof(suspend), 1); + if (err < 0) { + DHD_ERROR(("%s : failed to suspend pfn(error :%d)\n", __FUNCTION__, err)); +@@ -302,13 +299,13 @@ _dhd_pno_set(dhd_pub_t *dhd, const dhd_p + /* set bestn to calculate the max mscan which firmware supports */ + err = dhd_iovar(dhd, 0, "pfnmem", (char *)&_tmp, sizeof(_tmp), 1); + if (err < 0) { +- DHD_ERROR(("%s : failed to set pfnmem\n", __FUNCTION__)); ++ DHD_ERROR(("%s : failed to set pfnmscan\n", __FUNCTION__)); + goto exit; + } + /* get max mscan which the firmware supports */ + err = dhd_iovar(dhd, 0, "pfnmem", (char *)&_tmp, sizeof(_tmp), 0); + if (err < 0) { +- DHD_ERROR(("%s : failed to get pfnmem\n", __FUNCTION__)); ++ DHD_ERROR(("%s : failed to get pfnmscan\n", __FUNCTION__)); + goto exit; + } + DHD_PNO((" returned mscan : %d, set bestn : %d\n", _tmp, pfn_param.bestn)); +@@ -767,7 +764,7 @@ dhd_pno_stop_for_ssid(dhd_pub_t *dhd) + dhd_pno_get_for_batch(dhd, NULL, 0, PNO_STATUS_DISABLE); + /* save current pno_mode before calling dhd_pno_clean */ + mode = _pno_state->pno_mode; +- dhd_pno_clean(dhd); ++ _dhd_pno_clean(dhd); + /* restore previous pno_mode */ + _pno_state->pno_mode = mode; + if (_pno_state->pno_mode & DHD_PNO_BATCH_MODE) { +@@ -811,9 +808,9 @@ dhd_pno_stop_for_ssid(dhd_pub_t *dhd) + } + } + } else { +- err = dhd_pno_clean(dhd); ++ err = _dhd_pno_clean(dhd); + if (err < 0) { +- DHD_ERROR(("%s : failed to call dhd_pno_clean (err: %d)\n", ++ DHD_ERROR(("%s : failed to call _dhd_pno_clean (err: %d)\n", + __FUNCTION__, err)); + goto exit; + } +@@ -857,23 +854,15 @@ dhd_pno_set_for_ssid(dhd_pub_t *dhd, wlc + scan_fr, pno_repeat, pno_freq_expo_max, nchan)); + + _params = &(_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS]); +- if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) { +- DHD_ERROR(("%s : Legacy PNO mode was already started, " +- "will disable previous one to start new one\n", __FUNCTION__)); +- err = dhd_pno_stop_for_ssid(dhd); ++ if (!(_pno_state->pno_mode & DHD_PNO_LEGACY_MODE)) { ++ _pno_state->pno_mode |= DHD_PNO_LEGACY_MODE; ++ err = _dhd_pno_reinitialize_prof(dhd, _params, DHD_PNO_LEGACY_MODE); + if (err < 0) { +- DHD_ERROR(("%s : failed to stop legacy PNO (err %d)\n", ++ DHD_ERROR(("%s : failed to reinitialize profile (err %d)\n", + __FUNCTION__, err)); + goto exit; + } + } +- _pno_state->pno_mode |= DHD_PNO_LEGACY_MODE; +- err = _dhd_pno_reinitialize_prof(dhd, _params, DHD_PNO_LEGACY_MODE); +- if (err < 0) { +- DHD_ERROR(("%s : failed to reinitialize profile (err %d)\n", +- __FUNCTION__, err)); +- goto exit; +- } + memset(_chan_list, 0, sizeof(_chan_list)); + tot_nchan = nchan; + if (tot_nchan > 0 && channel_list) { +@@ -938,7 +927,7 @@ dhd_pno_set_for_ssid(dhd_pub_t *dhd, wlc + goto exit; + } + if ((err = _dhd_pno_add_ssid(dhd, ssid_list, nssid)) < 0) { +- DHD_ERROR(("failed to add ssid list(err %d), %d in firmware\n", err, nssid)); ++ DHD_ERROR(("failed to add ssid list (err %d) in firmware\n", err)); + goto exit; + } + for (i = 0; i < nssid; i++) { +@@ -1005,9 +994,6 @@ dhd_pno_set_for_batch(dhd_pub_t *dhd, st + __FUNCTION__)); + goto exit; + } +- } else { +- /* batch mode is already started */ +- return -EBUSY; + } + _params->params_batch.scan_fr = batch_params->scan_fr; + _params->params_batch.bestn = batch_params->bestn; +@@ -1249,7 +1235,6 @@ _dhd_pno_get_for_batch(dhd_pub_t *dhd, c + DHD_ERROR(("failed to allocate dhd_pno_bestnet_entry\n")); + goto exit; + } +- memset(pbestnet_entry, 0, BESTNET_ENTRY_SIZE); + pbestnet_entry->recorded_time = jiffies; /* record the current time */ + /* create header for the first entry */ + allocate_header = (i == 0)? TRUE : FALSE; +@@ -1328,15 +1313,6 @@ _dhd_pno_get_for_batch(dhd_pub_t *dhd, c + plnetinfo++; + } + } +- if (pscan_results->cnt_header == 0) { +- /* In case that we didn't get any data from the firmware +- * Remove the current scan_result list from get_bach.scan_results_list. +- */ +- DHD_PNO(("NO BATCH DATA from Firmware, Delete current SCAN RESULT LIST\n")); +- list_del(&pscan_results->list); +- MFREE(dhd->osh, pscan_results, SCAN_RESULTS_SIZE); +- _params->params_batch.get_batch.top_node_cnt--; +- } + /* increase total scan count using current scan count */ + _params->params_batch.get_batch.tot_scan_cnt += pscan_results->cnt_header; + +@@ -1365,14 +1341,10 @@ convert_format: + exit: + if (plbestnet) + MFREE(dhd->osh, plbestnet, PNO_BESTNET_LEN); +- if (_params) { +- _params->params_batch.get_batch.buf = NULL; +- _params->params_batch.get_batch.bufsize = 0; +- _params->params_batch.get_batch.bytes_written = err; +- } ++ _params->params_batch.get_batch.buf = NULL; ++ _params->params_batch.get_batch.bufsize = 0; + mutex_unlock(&_pno_state->pno_mutex); +- if (waitqueue_active(&_pno_state->get_batch_done.wait)) +- complete(&_pno_state->get_batch_done); ++ complete(&_pno_state->get_batch_done); + return err; + } + static void +@@ -1398,7 +1370,6 @@ int + dhd_pno_get_for_batch(dhd_pub_t *dhd, char *buf, int bufsize, int reason) + { + int err = BCME_OK; +- char *pbuf = buf; + dhd_pno_status_info_t *_pno_state; + struct dhd_pno_batch_params *params_batch; + NULL_CHECK(dhd, "dhd is NULL", err); +@@ -1418,19 +1389,13 @@ dhd_pno_get_for_batch(dhd_pub_t *dhd, ch + params_batch = &_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS].params_batch; + if (!(_pno_state->pno_mode & DHD_PNO_BATCH_MODE)) { + DHD_ERROR(("%s: Batching SCAN mode is not enabled\n", __FUNCTION__)); +- memset(pbuf, 0, bufsize); +- pbuf += sprintf(pbuf, "scancount=%d\n", 0); +- sprintf(pbuf, "%s", RESULTS_END_MARKER); +- err = strlen(buf); + goto exit; + } + params_batch->get_batch.buf = buf; + params_batch->get_batch.bufsize = bufsize; + params_batch->get_batch.reason = reason; +- params_batch->get_batch.bytes_written = 0; + schedule_work(&_pno_state->work); + wait_for_completion(&_pno_state->get_batch_done); +- err = params_batch->get_batch.bytes_written; + exit: + return err; + } +@@ -1466,7 +1431,7 @@ dhd_pno_stop_for_batch(dhd_pub_t *dhd) + _pno_state->pno_mode &= ~DHD_PNO_BATCH_MODE; + if (_pno_state->pno_mode & (DHD_PNO_LEGACY_MODE | DHD_PNO_HOTLIST_MODE)) { + mode = _pno_state->pno_mode; +- dhd_pno_clean(dhd); ++ _dhd_pno_clean(dhd); + _pno_state->pno_mode = mode; + /* restart Legacy PNO if the Legacy PNO is on */ + if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) { +@@ -1530,9 +1495,9 @@ dhd_pno_stop_for_batch(dhd_pub_t *dhd) + } + } + } else { +- err = dhd_pno_clean(dhd); ++ err = _dhd_pno_clean(dhd); + if (err < 0) { +- DHD_ERROR(("%s : failed to call dhd_pno_clean (err: %d)\n", ++ DHD_ERROR(("%s : failed to call _dhd_pno_clean (err: %d)\n", + __FUNCTION__, err)); + goto exit; + } +@@ -1725,9 +1690,9 @@ dhd_pno_stop_for_hotlist(dhd_pub_t *dhd) + dhd_pno_get_for_batch(dhd, NULL, 0, PNO_STATUS_DISABLE); + /* save current pno_mode before calling dhd_pno_clean */ + mode = _pno_state->pno_mode; +- err = dhd_pno_clean(dhd); ++ err = _dhd_pno_clean(dhd); + if (err < 0) { +- DHD_ERROR(("%s : failed to call dhd_pno_clean (err: %d)\n", ++ DHD_ERROR(("%s : failed to call _dhd_pno_clean (err: %d)\n", + __FUNCTION__, err)); + goto exit; + } +@@ -1777,9 +1742,9 @@ dhd_pno_stop_for_hotlist(dhd_pub_t *dhd) + } + } + } else { +- err = dhd_pno_clean(dhd); ++ err = _dhd_pno_clean(dhd); + if (err < 0) { +- DHD_ERROR(("%s : failed to call dhd_pno_clean (err: %d)\n", ++ DHD_ERROR(("%s : failed to call _dhd_pno_clean (err: %d)\n", + __FUNCTION__, err)); + goto exit; + } +@@ -1817,15 +1782,11 @@ dhd_pno_event_handler(dhd_pub_t *dhd, wl + { + struct dhd_pno_batch_params *params_batch; + params_batch = &_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS].params_batch; +- if (!waitqueue_active(&_pno_state->get_batch_done.wait)) { +- DHD_PNO(("%s : WLC_E_PFN_BEST_BATCHING\n", __FUNCTION__)); +- params_batch->get_batch.buf = NULL; +- params_batch->get_batch.bufsize = 0; +- params_batch->get_batch.reason = PNO_STATUS_EVENT; +- schedule_work(&_pno_state->work); +- } else +- DHD_PNO(("%s : WLC_E_PFN_BEST_BATCHING" +- "will skip this event\n", __FUNCTION__)); ++ DHD_PNO(("%s : WLC_E_PFN_BEST_BATCHING\n", __FUNCTION__)); ++ params_batch->get_batch.buf = NULL; ++ params_batch->get_batch.bufsize = 0; ++ params_batch->get_batch.reason = PNO_STATUS_EVENT; ++ schedule_work(&_pno_state->work); + break; + } + default: +@@ -1845,8 +1806,8 @@ int dhd_pno_init(dhd_pub_t *dhd) + if (dhd->pno_state) + goto exit; + dhd->pno_state = MALLOC(dhd->osh, sizeof(dhd_pno_status_info_t)); +- NULL_CHECK(dhd->pno_state, "failed to create dhd_pno_state", err); + memset(dhd->pno_state, 0, sizeof(dhd_pno_status_info_t)); ++ NULL_CHECK(dhd, "failed to create dhd_pno_state", err); + /* need to check whether current firmware support batching and hotlist scan */ + _pno_state = PNO_GET_PNOSTATE(dhd); + _pno_state->wls_supported = TRUE; +@@ -1866,20 +1827,12 @@ exit: + int dhd_pno_deinit(dhd_pub_t *dhd) + { + int err = BCME_OK; +- dhd_pno_status_info_t *_pno_state; +- dhd_pno_params_t *_params; ++ dhd_pno_status_info_t *_pno_state = PNO_GET_PNOSTATE(dhd); + NULL_CHECK(dhd, "dhd is NULL", err); +- + DHD_PNO(("%s enter\n", __FUNCTION__)); +- _pno_state = PNO_GET_PNOSTATE(dhd); +- NULL_CHECK(_pno_state, "pno_state is NULL", err); +- if (_pno_state->pno_mode & DHD_PNO_BATCH_MODE) { +- _params = &_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS]; +- /* clear resource if the BATCH MODE is on */ +- _dhd_pno_reinitialize_prof(dhd, _params, DHD_PNO_BATCH_MODE); +- } + cancel_work_sync(&_pno_state->work); +- MFREE(dhd->osh, _pno_state, sizeof(dhd_pno_status_info_t)); ++ if (dhd->pno_state) ++ MFREE(dhd->osh, dhd->pno_state, sizeof(dhd_pno_status_info_t)); + dhd->pno_state = NULL; + return err; + } +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/dhd_pno.h linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_pno.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/dhd_pno.h 2014-01-27 01:30:30.109433432 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_pno.h 2014-02-15 00:43:44.796014158 +0100 +@@ -152,7 +152,6 @@ struct dhd_pno_get_batch_info { + uint32 expired_tot_scan_cnt; + uint32 top_node_cnt; + uint32 bufsize; +- uint32 bytes_written; + int reason; + struct list_head scan_results_list; + struct list_head expired_scan_results_list; +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/dhd_proto.h linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_proto.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/dhd_proto.h 2014-01-27 01:30:30.100433249 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_proto.h 2014-02-15 00:43:44.791014047 +0100 +@@ -4,7 +4,7 @@ + * Provides type definitions and function prototypes used to link the + * DHD OS, bus, and protocol modules. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -24,7 +24,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: dhd_proto.h 390836 2013-03-13 23:43:53Z $ ++ * $Id: dhd_proto.h 343390 2012-07-06 22:34:19Z $ + */ + + #ifndef _dhd_proto_h_ +@@ -54,6 +54,10 @@ extern int dhd_prot_init(dhd_pub_t *dhdp + + /* Stop protocol: sync w/dongle state. */ + extern void dhd_prot_stop(dhd_pub_t *dhdp); ++#ifdef PROP_TXSTATUS ++extern int dhd_wlfc_init(dhd_pub_t *dhd); ++extern void dhd_wlfc_deinit(dhd_pub_t *dhd); ++#endif /* PROP_TXSTATUS */ + + /* Add any protocol-specific data header. + * Caller must reserve prot_hdrlen prepend space. +@@ -83,6 +87,12 @@ extern int dhd_ioctl(dhd_pub_t * dhd_pub + + extern int dhd_preinit_ioctls(dhd_pub_t *dhd); + ++#ifdef PROP_TXSTATUS ++extern int dhd_wlfc_enque_sendq(void* state, int prec, void* p); ++extern int dhd_wlfc_commit_packets(void* state, f_commitpkt_t fcommit, void* commit_ctx); ++extern void dhd_wlfc_cleanup(dhd_pub_t *dhd); ++#endif /* PROP_TXSTATUS */ ++ + extern int dhd_process_pkt_reorder_info(dhd_pub_t *dhd, uchar *reorder_info_buf, + uint reorder_info_len, void **pkt, uint32 *free_buf_count); + +@@ -94,6 +104,8 @@ extern int dhd_process_pkt_reorder_info( + #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 */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/dhd_sdio.c linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_sdio.c +--- linux-sunxi/drivers/net/wireless/bcmdhd/dhd_sdio.c 2014-01-27 01:30:30.109433432 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_sdio.c 2014-02-15 00:43:44.796014158 +0100 +@@ -1,7 +1,7 @@ + /* + * DHD Bus Module for SDIO + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -21,7 +21,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: dhd_sdio.c 419981 2013-08-23 19:49:45Z $ ++ * $Id: dhd_sdio.c 373330 2012-12-07 04:46:17Z $ + */ + + #include +@@ -66,11 +66,6 @@ + #include + #include + +-bool dhd_mp_halting(dhd_pub_t *dhdp); +-extern void bcmsdh_waitfor_iodrain(void *sdh); +-extern void bcmsdh_reject_ioreqs(void *sdh, bool reject); +-extern bool bcmsdh_fatal_error(void *sdh); +- + #ifndef DHDSDIO_MEM_DUMP_FNAME + #define DHDSDIO_MEM_DUMP_FNAME "mem_dump" + #endif +@@ -81,13 +76,10 @@ extern bool bcmsdh_fatal_error(void *sd + #define PRIOMASK 7 + + #define TXRETRIES 2 /* # of retries for tx frames */ +-#ifndef DHD_RXBOUND ++ + #define DHD_RXBOUND 50 /* Default for max rx frames in one scheduling */ +-#endif + +-#ifndef DHD_TXBOUND + #define DHD_TXBOUND 20 /* Default for max tx frames in one scheduling */ +-#endif + + #define DHD_TXMINMAX 1 /* Max tx frames if rx still pending */ + +@@ -159,10 +151,12 @@ DHD_SPINWAIT_SLEEP_INIT(sdioh_spinwait_s + extern void bcmsdh_set_irq(int flag); + #endif + #ifdef PROP_TXSTATUS +-extern void dhd_wlfc_txcomplete(dhd_pub_t *dhd, void *txp, bool success); ++extern void dhd_wlfc_txcomplete(dhd_pub_t *dhd, void *txp, bool success, bool wlfc_locked); + extern void dhd_wlfc_trigger_pktcommit(dhd_pub_t *dhd); + #endif +- ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) ++DEFINE_MUTEX(_dhd_sdio_mutex_lock_); ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */ + + #ifdef DHD_DEBUG + /* Device console log buffer state */ +@@ -187,17 +181,14 @@ typedef struct dhd_console { + #define MIN_RSRC_SR 0x3 + #define CORE_CAPEXT_ADDR (SI_ENUM_BASE + 0x64c) + #define CORE_CAPEXT_SR_SUPPORTED_MASK (1 << 1) +-#define RCTL_MACPHY_DISABLE_MASK (1 << 26) +-#define RCTL_LOGIC_DISABLE_MASK (1 << 27) ++#define RCTL_MACPHY_DISABLE_MASK (1 << 26) ++#define RCTL_LOGIC_DISABLE_MASK (1 << 27) + + #define OOB_WAKEUP_ENAB(bus) ((bus)->_oobwakeup) + #define GPIO_DEV_SRSTATE 16 /* Host gpio17 mapped to device gpio0 SR state */ + #define GPIO_DEV_SRSTATE_TIMEOUT 320000 /* 320ms */ + #define GPIO_DEV_WAKEUP 17 /* Host gpio17 mapped to device gpio1 wakeup */ + #define CC_CHIPCTRL2_GPIO1_WAKEUP (1 << 0) +-#define CC_CHIPCTRL3_SR_ENG_ENABLE (1 << 2) +-#define OVERFLOW_BLKSZ512_WM 48 +-#define OVERFLOW_BLKSZ512_MES 80 + + #define CC_PMUCC3 (0x3) + /* Private data for SDIO bus interaction */ +@@ -389,7 +380,6 @@ static int tx_packets[NUMPRIO]; + const uint dhd_deferred_tx = 1; + + extern uint dhd_watchdog_ms; +- + extern void dhd_os_wd_timer(void *bus, uint wdtick); + + /* Tx/Rx bounds */ +@@ -398,15 +388,10 @@ uint dhd_rxbound; + uint dhd_txminmax = DHD_TXMINMAX; + + /* override the RAM size if possible */ +-#define DONGLE_MIN_RAMSIZE (128 *1024) +-int dhd_dongle_ramsize; +- +-uint dhd_doflow = TRUE; +-uint dhd_dpcpoll = FALSE; +- +-module_param(dhd_doflow, uint, 0644); +-module_param(dhd_dpcpoll, uint, 0644); ++#define DONGLE_MIN_MEMSIZE (128 *1024) ++int dhd_dongle_memsize; + ++static bool dhd_doflow; + static bool dhd_alignctl; + + static bool sd1idle; +@@ -420,7 +405,7 @@ static uint mesbusyctrl = 80; + #else + static const uint watermark = 8; + static const uint mesbusyctrl = 0; +-#endif ++#endif + static const uint firstread = DHD_FIRSTREAD; + + #define HDATLEN (firstread - (SDPCM_HDRLEN)) +@@ -431,6 +416,61 @@ static const uint retry_limit = 2; + /* Force even SD lengths (some host controllers mess up on odd bytes) */ + static bool forcealign; + ++#define FW_TYPE_STA 0 ++#define FW_TYPE_APSTA 1 ++#define FW_TYPE_P2P 2 ++#define FW_TYPE_MFG 3 ++#define FW_TYPE_G 0 ++#define FW_TYPE_AG 1 ++ ++const static char *bcm40183b2_fw_name[] = { ++ "fw_bcm40183b2.bin", ++ "fw_bcm40183b2_apsta.bin", ++ "fw_bcm40183b2_p2p.bin", ++ "fw_bcm40183b2_mfg.bin" ++}; ++ ++const static char *bcm40183b2ag_fw_name[] = { ++ "fw_bcm40183b2_ag.bin", ++ "fw_bcm40183b2_ag_apsta.bin", ++ "fw_bcm40183b2_ag_p2p.bin", ++ "fw_bcm40183b2_ag_mfg.bin" ++}; ++ ++const static char *bcm40181a0_fw_name[] = { ++ "fw_bcm40181a0.bin", ++ "fw_bcm40181a0_apsta.bin", ++ "fw_bcm40181a0_p2p.bin", ++ "fw_bcm40181a0_mfg.bin" ++}; ++ ++const static char *bcm40181a2_fw_name[] = { ++ "fw_bcm40181a2.bin", ++ "fw_bcm40181a2_apsta.bin", ++ "fw_bcm40181a2_p2p.bin", ++ "fw_bcm40181a2_mfg.bin" ++}; ++ ++const static char *bcm43341b0ag_fw_name[] = { ++ "fw_bcm43341b0_ag.bin", ++ "fw_bcm43341b0_ag_apsta.bin", ++ "fw_bcm43341b0_ag_p2p.bin", ++ "fw_bcm43341b0_ag_mfg.bin" ++}; ++ ++const static char *bcm43241b4ag_fw_name[] = { ++ "fw_bcm43241b4_ag.bin", ++ "fw_bcm43241b4_ag_apsta.bin", ++ "fw_bcm43241b4_ag_p2p.bin", ++ "fw_bcm43241b4_ag_mfg.bin" ++}; ++ ++#define BCM4330B2_CHIP_REV 4 ++#define BCM43362A0_CHIP_REV 0 ++#define BCM43362A2_CHIP_REV 1 ++#define BCM43341B0_CHIP_REV 2 ++#define BCM43241B4_CHIP_REV 5 ++ + #define ALIGNMENT 4 + + #if defined(OOB_INTR_ONLY) && defined(HW_OOB) +@@ -458,6 +498,7 @@ static const uint max_roundup = 512; + /* Try doing readahead */ + static bool dhd_readahead; + ++ + /* To check if there's window offered */ + #define DATAOK(bus) \ + (((uint8)(bus->tx_max - bus->tx_seq) > 1) && \ +@@ -568,7 +609,7 @@ static bool dhdsdio_probe_init(dhd_bus_t + static void dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh, bool dongle_isolation, + bool reset_flag); + +-static void dhd_dongle_setramsize(struct dhd_bus *bus, int mem_size); ++static void dhd_dongle_setmemsize(struct dhd_bus *bus, int mem_size); + static int dhd_bcmsdh_recv_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags, + uint8 *buf, uint nbytes, + void *pkt, bcmsdh_cmplt_fn_t complete, void *handle); +@@ -576,7 +617,7 @@ static int dhd_bcmsdh_send_buf(dhd_bus_t + uint8 *buf, uint nbytes, + void *pkt, bcmsdh_cmplt_fn_t complete, void *handle); + #ifdef BCMSDIOH_TXGLOM +-static void dhd_bcmsdh_glom_post(dhd_bus_t *bus, uint8 *frame, void *pkt, uint len); ++static void dhd_bcmsdh_glom_post(dhd_bus_t *bus, uint8 *frame, uint len); + static void dhd_bcmsdh_glom_clear(dhd_bus_t *bus); + #endif + +@@ -598,48 +639,15 @@ extern uint32 dhd_get_htsf(void *dhd, in + #endif /* WLMEDIA_HTSF */ + + static void +-dhd_overflow_war(struct dhd_bus *bus) +-{ +- int err; +- uint8 devctl, wm, mes; +- +- /* See .ppt in PR for these recommended values */ +- if (bus->blocksize == 512) { +- wm = OVERFLOW_BLKSZ512_WM; +- mes = OVERFLOW_BLKSZ512_MES; +- } else { +- mes = bus->blocksize/4; +- wm = bus->blocksize/4; +- } +- +- +- /* Update watermark */ +- bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, wm, &err); +- +- devctl = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err); +- devctl |= SBSDIO_DEVCTL_F2WM_ENAB; +- bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err); +- +- /* Update MES */ +- bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_MESBUSYCTRL, +- (mes | SBSDIO_MESBUSYCTRL_ENAB), &err); +- +- DHD_INFO(("Apply overflow WAR: 0x%02x 0x%02x 0x%02x\n", +- bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err), +- bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, &err), +- bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_MESBUSYCTRL, &err))); +-} +- +-static void +-dhd_dongle_setramsize(struct dhd_bus *bus, int mem_size) ++dhd_dongle_setmemsize(struct dhd_bus *bus, int mem_size) + { +- int32 min_size = DONGLE_MIN_RAMSIZE; +- /* Restrict the ramsize to user specified limit */ ++ int32 min_size = DONGLE_MIN_MEMSIZE; ++ /* Restrict the memsize to user specified limit */ + DHD_ERROR(("user: Restrict the dongle ram size to %d, min accepted %d\n", +- dhd_dongle_ramsize, min_size)); +- if ((dhd_dongle_ramsize > min_size) && +- (dhd_dongle_ramsize < (int32)bus->orig_ramsize)) +- bus->ramsize = dhd_dongle_ramsize; ++ dhd_dongle_memsize, min_size)); ++ if ((dhd_dongle_memsize > min_size) && ++ (dhd_dongle_memsize < (int32)bus->orig_ramsize)) ++ bus->ramsize = dhd_dongle_memsize; + } + + static int +@@ -688,17 +696,15 @@ static bool + dhdsdio_sr_cap(dhd_bus_t *bus) + { + bool cap = FALSE; +- uint32 core_capext, addr, data; ++ uint32 min = 0, core_capext, addr, data; + if (bus->sih->chip == BCM4324_CHIP_ID) { + addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_addr); + data = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_data); + bcmsdh_reg_write(bus->sdh, addr, 4, 3); + core_capext = bcmsdh_reg_read(bus->sdh, data, 4); +- } else if (bus->sih->chip == BCM4330_CHIP_ID) { ++ } else if (bus->sih->chip == BCM4330_CHIP_ID || bus->sih->chip == BCM43362_CHIP_ID) { + core_capext = FALSE; +- } else if ((bus->sih->chip == BCM4335_CHIP_ID) || +- (bus->sih->chip == BCM4339_CHIP_ID) || +- (bus->sih->chip == BCM4350_CHIP_ID)) { ++ } else if (bus->sih->chip == BCM4335_CHIP_ID) { + core_capext = TRUE; + } else { + core_capext = bcmsdh_reg_read(bus->sdh, CORE_CAPEXT_ADDR, 4); +@@ -709,20 +715,16 @@ dhdsdio_sr_cap(dhd_bus_t *bus) + + if (bus->sih->chip == BCM4324_CHIP_ID) { + /* FIX: Should change to query SR control register instead */ +- cap = TRUE; +- } else if ((bus->sih->chip == BCM4335_CHIP_ID) || +- (bus->sih->chip == BCM4339_CHIP_ID)) { ++ min = bcmsdh_reg_read(bus->sdh, MIN_RSRC_ADDR, 4); ++ if (min == MIN_RSRC_SR) ++ cap = TRUE; ++ } else if (bus->sih->chip == BCM4335_CHIP_ID) { + uint32 enabval = 0; + addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_addr); + data = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_data); + bcmsdh_reg_write(bus->sdh, addr, 4, CC_PMUCC3); + enabval = bcmsdh_reg_read(bus->sdh, data, 4); + +- if ((bus->sih->chip == BCM4350_CHIP_ID) || +- 0) +- enabval &= CC_CHIPCTRL3_SR_ENG_ENABLE; +- +- + if (enabval) + cap = TRUE; + } else { +@@ -738,6 +740,7 @@ dhdsdio_sr_cap(dhd_bus_t *bus) + static int + dhdsdio_srwar_init(dhd_bus_t *bus) + { ++ + bcmsdh_gpio_init(bus->sdh); + + #ifdef USE_OOB_GPIO1 +@@ -806,8 +809,7 @@ dhdsdio_clk_kso_init(dhd_bus_t *bus) + } + + #define KSO_DBG(x) +-#define KSO_WAIT_US 50 +-#define MAX_KSO_ATTEMPTS (PMU_MAX_TRANSITION_DLY/KSO_WAIT_US) ++#define MAX_KSO_ATTEMPTS 64 + static int + dhdsdio_clk_kso_enab(dhd_bus_t *bus, bool on) + { +@@ -825,9 +827,10 @@ dhdsdio_clk_kso_enab(dhd_bus_t *bus, boo + cmp_val = SBSDIO_FUNC1_SLEEPCSR_KSO_MASK | SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK; + bmask = cmp_val; + +- OSL_SLEEP(3); ++ msleep(3); ++ + } else { +- /* Put device to sleep, turn off KSO */ ++ /* Put device to sleep, turn off KSO */ + cmp_val = 0; + bmask = SBSDIO_FUNC1_SLEEPCSR_KSO_MASK; + } +@@ -838,15 +841,17 @@ dhdsdio_clk_kso_enab(dhd_bus_t *bus, boo + break; + + KSO_DBG(("%s> KSO wr/rd retry:%d, ERR:%x \n", __FUNCTION__, try_cnt, err)); +- OSL_DELAY(KSO_WAIT_US); ++ OSL_DELAY(50); + + bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, wr_val, &err); ++ + } while (try_cnt++ < MAX_KSO_ATTEMPTS); + + +- if (try_cnt > 2) ++ if (try_cnt > 1) { + KSO_DBG(("%s> op:%s, try_cnt:%d, rd_val:%x, ERR:%x \n", + __FUNCTION__, (on ? "KSO_SET" : "KSO_CLR"), try_cnt, rd_val, err)); ++ } + + if (try_cnt > MAX_KSO_ATTEMPTS) { + DHD_ERROR(("%s> op:%s, ERROR: try_cnt:%d, rd_val:%x, ERR:%x \n", +@@ -878,7 +883,16 @@ dhdsdio_clk_kso_iovar(dhd_bus_t *bus, bo + dhdsdio_clkctl(bus, CLK_SDONLY, FALSE); + } + ++ /* Double-write to be safe in case transition of AOS */ + dhdsdio_clk_kso_enab(bus, TRUE); ++ dhdsdio_clk_kso_enab(bus, TRUE); ++ OSL_DELAY(4000); ++ ++ /* Wait for device ready during transition to wake-up */ ++ SPINWAIT(((dhdsdio_sleepcsr_get(bus)) != ++ (SBSDIO_FUNC1_SLEEPCSR_KSO_MASK | ++ SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK)), ++ (10000)); + + DHD_ERROR(("%s: sleepcsr: 0x%x\n", __FUNCTION__, + dhdsdio_sleepcsr_get(bus))); +@@ -960,10 +974,8 @@ dhdsdio_clk_devsleep_iovar(dhd_bus_t *bu + #else + err = dhdsdio_clk_kso_enab(bus, FALSE); + if (OOB_WAKEUP_ENAB(bus)) +- { + err = bcmsdh_gpioout(bus->sdh, GPIO_DEV_WAKEUP, FALSE); /* GPIO_1 is off */ +- } +-#endif /* USE_CMD14 */ ++#endif + } else { + /* Exit Sleep */ + /* Make sure we have SD bus access */ +@@ -973,8 +985,7 @@ dhdsdio_clk_devsleep_iovar(dhd_bus_t *bu + } + + if ((bus->sih->chip == BCM4334_CHIP_ID) && (bus->sih->chiprev == 2)) { +- SPINWAIT_SLEEP(sdioh_spinwait_sleep, +- (bcmsdh_gpioin(bus->sdh, GPIO_DEV_SRSTATE) != TRUE), ++ SPINWAIT((bcmsdh_gpioin(bus->sdh, GPIO_DEV_SRSTATE) != TRUE), + GPIO_DEV_SRSTATE_TIMEOUT); + + if (bcmsdh_gpioin(bus->sdh, GPIO_DEV_SRSTATE) == FALSE) { +@@ -1010,13 +1021,12 @@ dhdsdio_clk_devsleep_iovar(dhd_bus_t *bu + } + #else + if (OOB_WAKEUP_ENAB(bus)) +- { + err = bcmsdh_gpioout(bus->sdh, GPIO_DEV_WAKEUP, TRUE); /* GPIO_1 is on */ +- } ++ + do { + err = dhdsdio_clk_kso_enab(bus, TRUE); + if (err) +- OSL_SLEEP(10); ++ OSL_DELAY(10000); + } while ((err != 0) && (++retry < 3)); + + if (err != 0) { +@@ -1029,8 +1039,7 @@ dhdsdio_clk_devsleep_iovar(dhd_bus_t *bu + uint8 csr; + + /* Wait for device ready during transition to wake-up */ +- SPINWAIT_SLEEP(sdioh_spinwait_sleep, +- (((csr = dhdsdio_sleepcsr_get(bus)) & ++ SPINWAIT((((csr = dhdsdio_sleepcsr_get(bus)) & + SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK) != + (SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK)), (20000)); + +@@ -1042,8 +1051,7 @@ dhdsdio_clk_devsleep_iovar(dhd_bus_t *bu + err = BCME_NODEVICE; + } + +- SPINWAIT_SLEEP(sdioh_spinwait_sleep, +- (((csr = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, ++ SPINWAIT((((csr = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, + SBSDIO_FUNC1_CHIPCLKCSR, &err)) & SBSDIO_HT_AVAIL) != + (SBSDIO_HT_AVAIL)), (10000)); + +@@ -1074,6 +1082,9 @@ dhdsdio_htclk(dhd_bus_t *bus, bool on, b + + DHD_TRACE(("%s: Enter\n", __FUNCTION__)); + ++#if defined(OOB_INTR_ONLY) ++ pendok = FALSE; ++#endif + clkctl = 0; + sdh = bus->sdh; + +@@ -1109,6 +1120,12 @@ dhdsdio_htclk(dhd_bus_t *bus, bool on, b + ht_avail_error = 0; + } + ++ if (pendok && ++ ((bus->sih->buscoretype == PCMCIA_CORE_ID) && (bus->sih->buscorerev == 9))) { ++ uint32 dummy, retries; ++ R_SDREG(dummy, &bus->regs->clockctlstatus, retries); ++ BCM_REFERENCE(dummy); ++ } + + /* Check current status */ + clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); +@@ -1117,7 +1134,6 @@ dhdsdio_htclk(dhd_bus_t *bus, bool on, b + return BCME_ERROR; + } + +-#if !defined(OOB_INTR_ONLY) + /* Go to pending and await interrupt if appropriate */ + if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) { + /* Allow only clock-available interrupt */ +@@ -1133,15 +1149,11 @@ dhdsdio_htclk(dhd_bus_t *bus, bool on, b + DHD_INFO(("CLKCTL: set PENDING\n")); + bus->clkstate = CLK_PENDING; + return BCME_OK; +- } else +-#endif /* !defined (OOB_INTR_ONLY) */ +- { +- 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); +- } ++ } 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 */ +@@ -1185,7 +1197,6 @@ dhdsdio_htclk(dhd_bus_t *bus, bool on, b + #endif /* DHD_USE_IDLECOUNT */ + } 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); +@@ -1465,7 +1476,6 @@ dhdsdio_bussleep(dhd_bus_t *bus, bool sl + return err; + } + +- + #if defined(OOB_INTR_ONLY) + void + dhd_enable_oob_intr(struct dhd_bus *bus, bool enable) +@@ -1497,234 +1507,6 @@ dhd_enable_oob_intr(struct dhd_bus *bus, + } + #endif + +-#ifdef DHDTCPACK_SUPPRESS +-extern bool dhd_use_tcpack_suppress; +- +-/* Please be sure this function is called under dhd_os_tcpacklock() */ +-void dhd_onoff_tcpack_sup(void *pub, bool on) +-{ +- dhd_pub_t *dhdp = (dhd_pub_t *)pub; +- +- if (dhd_use_tcpack_suppress != on) { +- +- DHD_ERROR(("dhd_onoff_tcpack_sup: %d -> %d\n", dhd_use_tcpack_suppress, on)); +- dhd_use_tcpack_suppress = on; +- dhdp->tcp_ack_info_cnt = 0; +- bzero(dhdp->tcp_ack_info_tbl, sizeof(struct tcp_ack_info)*MAXTCPSTREAMS); +- +- } else +- DHD_ERROR(("dhd_onoff_tcpack_sup: alread %d\n", on)); +- +- return; +-} +- +-inline void dhd_tcpack_check_xmit(dhd_pub_t *dhdp, void *pkt) +-{ +- uint8 i; +- tcp_ack_info_t *tcp_ack_info = NULL; +- int tbl_cnt; +- +- dhd_os_tcpacklock(dhdp); +- tbl_cnt = dhdp->tcp_ack_info_cnt; +- for (i = 0; i < tbl_cnt; i++) { +- tcp_ack_info = &dhdp->tcp_ack_info_tbl[i]; +- if (tcp_ack_info->p_tcpackinqueue == pkt) { +- /* This pkt is being transmitted so remove the tcp_ack_info of it. +- * compact the array unless the last element, +- * then the pkt's array is removed. +- */ +- if (i < tbl_cnt-1) { +- memmove(&dhdp->tcp_ack_info_tbl[i], +- &dhdp->tcp_ack_info_tbl[i+1], +- sizeof(struct tcp_ack_info)*(tbl_cnt - (i+1))); +- } +- bzero(&dhdp->tcp_ack_info_tbl[tbl_cnt-1], sizeof(struct tcp_ack_info)); +- if (--dhdp->tcp_ack_info_cnt < 0) { +- DHD_ERROR(("dhdsdio_sendfromq:(ERROR) tcp_ack_info_cnt %d" +- " Stop using tcpack_suppress\n", dhdp->tcp_ack_info_cnt)); +- dhd_onoff_tcpack_sup(dhdp, FALSE); +- } +- break; +- } +- } +- dhd_os_tcpackunlock(dhdp); +-} +- +-bool +-dhd_tcpack_suppress(dhd_pub_t *dhdp, void *pkt) +-{ +- uint8 *eh_header; +- uint16 eh_type; +- uint8 *ip_header; +- uint8 *tcp_header; +- uint32 ip_hdr_len; +- uint32 cur_framelen; +- uint8 bdc_hdr_len = BDC_HEADER_LEN; +- uint8 wlfc_hdr_len = 0; +- uint8 *data = PKTDATA(dhdp->osh, pkt); +- cur_framelen = PKTLEN(dhdp->osh, pkt); +- +-#ifdef PROP_TXSTATUS +- /* In this case, BDC header is not pushed in dhd_sendpkt() */ +- if (dhdp->wlfc_state) { +- bdc_hdr_len = 0; +- wlfc_hdr_len = 8; +- } +-#endif +- if (cur_framelen < bdc_hdr_len + ETHER_HDR_LEN) { +- DHD_TRACE(("dhd_tcpack_suppress: Too short packet length %d\n", cur_framelen)); +- return FALSE; +- } +- +- /* Get rid of BDC header */ +- eh_header = data + bdc_hdr_len; +- cur_framelen -= bdc_hdr_len; +- eh_type = eh_header[12] << 8 | eh_header[13]; +- +- if (eh_type != ETHER_TYPE_IP) { +- DHD_TRACE(("dhd_tcpack_suppress: Not a IP packet 0x%x\n", eh_type)); +- return FALSE; +- } +- +- DHD_TRACE(("dhd_tcpack_suppress: IP pkt! 0x%x\n", eh_type)); +- +- ip_header = eh_header + ETHER_HDR_LEN; +- cur_framelen -= ETHER_HDR_LEN; +- ip_hdr_len = 4 * (ip_header[0] & 0x0f); +- +- if ((ip_header[0] & 0xf0) != 0x40) { +- DHD_TRACE(("dhd_tcpack_suppress: Not IPv4!\n")); +- return FALSE; +- } +- +- if (cur_framelen < ip_hdr_len) { +- DHD_ERROR(("dhd_tcpack_suppress: IP packet length %d wrong!\n", cur_framelen)); +- return FALSE; +- } +- +- /* not tcp */ +- if (ip_header[9] != 0x06) { +- DHD_TRACE(("dhd_tcpack_suppress: Not a TCP packet 0x%x\n", ip_header[9])); +- return FALSE; +- } +- +- DHD_TRACE(("dhd_tcpack_suppress: TCP pkt!\n")); +- +- tcp_header = ip_header + ip_hdr_len; +- +- /* is it an ack ? */ +- if (tcp_header[13] == 0x10) { +-#if defined(DHD_DEBUG) +- uint32 tcp_seq_num = tcp_header[4] << 24 | tcp_header[5] << 16 | +- tcp_header[6] << 8 | tcp_header[7]; +-#endif +- uint32 tcp_ack_num = tcp_header[8] << 24 | tcp_header[9] << 16 | +- tcp_header[10] << 8 | tcp_header[11]; +- uint16 ip_tcp_ttllen = (ip_header[3] & 0xff) + (ip_header[2] << 8); +- uint32 tcp_hdr_len = 4*((tcp_header[12] & 0xf0) >> 4); +- DHD_TRACE(("dhd_tcpack_suppress: TCP ACK seq %ud ack %ud\n", +- tcp_seq_num, tcp_ack_num)); +- +- +- /* zero length ? */ +- if (ip_tcp_ttllen == ip_hdr_len + tcp_hdr_len) { +- int i; +- tcp_ack_info_t *tcp_ack_info = NULL; +- DHD_TRACE(("dhd_tcpack_suppress: TCP ACK zero length\n")); +- /* Look for tcp_ack_info that has the same +- * ip src/dst addrs and tcp src/dst ports +- */ +- dhd_os_tcpacklock(dhdp); +- for (i = 0; i < dhdp->tcp_ack_info_cnt; i++) { +- if (dhdp->tcp_ack_info_tbl[i].p_tcpackinqueue && +- !memcmp(&ip_header[12], dhdp->tcp_ack_info_tbl[i].ipaddrs, 8) && +- !memcmp(tcp_header, dhdp->tcp_ack_info_tbl[i].tcpports, 4)) { +- tcp_ack_info = &dhdp->tcp_ack_info_tbl[i]; +- break; +- } +- } +- +- if (i == dhdp->tcp_ack_info_cnt && i < MAXTCPSTREAMS) +- tcp_ack_info = &dhdp->tcp_ack_info_tbl[dhdp->tcp_ack_info_cnt++]; +- +- if (!tcp_ack_info) { +- DHD_TRACE(("dhd_tcpack_suppress: No empty tcp ack info" +- "%d %d %d %d, %d %d %d %d\n", +- tcp_header[0], tcp_header[1], tcp_header[2], tcp_header[3], +- dhdp->tcp_ack_info_tbl[i].tcpports[0], +- dhdp->tcp_ack_info_tbl[i].tcpports[1], +- dhdp->tcp_ack_info_tbl[i].tcpports[2], +- dhdp->tcp_ack_info_tbl[i].tcpports[3])); +- dhd_os_tcpackunlock(dhdp); +- return FALSE; +- } +- +- if (tcp_ack_info->p_tcpackinqueue) { +- if (tcp_ack_num > tcp_ack_info->tcpack_number) { +- void *prevpkt = tcp_ack_info->p_tcpackinqueue; +- uint8 pushed_len = SDPCM_HDRLEN + +- (BDC_HEADER_LEN - bdc_hdr_len) + wlfc_hdr_len; +-#ifdef PROP_TXSTATUS +- /* In case the prev pkt is delayenqueued +- * but not delayedequeued yet, it may not have +- * any additional header yet. +- */ +- if (dhdp->wlfc_state && (PKTLEN(dhdp->osh, prevpkt) == +- tcp_ack_info->ip_tcp_ttllen + ETHER_HDR_LEN)) +- pushed_len = 0; +-#endif +- if ((ip_tcp_ttllen == tcp_ack_info->ip_tcp_ttllen) && +- (PKTLEN(dhdp->osh, pkt) == +- PKTLEN(dhdp->osh, prevpkt) - pushed_len)) { +- bcopy(PKTDATA(dhdp->osh, pkt), +- PKTDATA(dhdp->osh, prevpkt) + pushed_len, +- PKTLEN(dhdp->osh, pkt)); +- PKTFREE(dhdp->osh, pkt, FALSE); +- DHD_TRACE(("dhd_tcpack_suppress: pkt 0x%p" +- " TCP ACK replace %ud -> %ud\n", prevpkt, +- tcp_ack_info->tcpack_number, tcp_ack_num)); +- tcp_ack_info->tcpack_number = tcp_ack_num; +- dhd_os_tcpackunlock(dhdp); +- return TRUE; +- } else +- DHD_TRACE(("dhd_tcpack_suppress: len mismatch" +- " %d(%d) %d(%d)\n", +- PKTLEN(dhdp->osh, pkt), ip_tcp_ttllen, +- PKTLEN(dhdp->osh, prevpkt), +- tcp_ack_info->ip_tcp_ttllen)); +- } else { +-#ifdef TCPACK_TEST +- void *prevpkt = tcp_ack_info->p_tcpackinqueue; +-#endif +- DHD_TRACE(("dhd_tcpack_suppress: TCP ACK number reverse" +- " prev %ud (0x%p) new %ud (0x%p)\n", +- tcp_ack_info->tcpack_number, +- tcp_ack_info->p_tcpackinqueue, +- tcp_ack_num, pkt)); +-#ifdef TCPACK_TEST +- if (PKTLEN(dhdp->osh, pkt) == PKTLEN(dhdp->osh, prevpkt)) { +- PKTFREE(dhdp->osh, pkt, FALSE); +- dhd_os_tcpackunlock(dhdp); +- return TRUE; +- } +-#endif +- } +- } else { +- tcp_ack_info->p_tcpackinqueue = pkt; +- tcp_ack_info->tcpack_number = tcp_ack_num; +- tcp_ack_info->ip_tcp_ttllen = ip_tcp_ttllen; +- bcopy(&ip_header[12], tcp_ack_info->ipaddrs, 8); +- bcopy(tcp_header, tcp_ack_info->tcpports, 4); +- } +- dhd_os_tcpackunlock(dhdp); +- } else +- DHD_TRACE(("dhd_tcpack_suppress: TCP ACK with DATA len %d\n", +- ip_tcp_ttllen - ip_hdr_len - tcp_hdr_len)); +- } +- return FALSE; +-} +-#endif /* DHDTCPACK_SUPPRESS */ +- + /* Writes a HW/SW header into the packet and sends it. */ + /* Assumes: (a) header space already there, (b) caller holds lock */ + static int +@@ -1733,10 +1515,9 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, + int ret; + osl_t *osh; + uint8 *frame; +- uint16 len, pad1 = 0, act_len = 0; ++ uint16 len, pad1 = 0; + uint32 swheader; + uint retries = 0; +- uint32 real_pad = 0; + bcmsdh_info_t *sdh; + void *new; + int i; +@@ -1749,17 +1530,12 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, + htsfts_t *htsf_ts; + #endif + ++ + DHD_TRACE(("%s: Enter\n", __FUNCTION__)); + + sdh = bus->sdh; + osh = bus->dhd->osh; + +-#ifdef DHDTCPACK_SUPPRESS +- if (dhd_use_tcpack_suppress) { +- dhd_tcpack_check_xmit(bus->dhd, pkt); +- } +-#endif /* DHDTCPACK_SUPPRESS */ +- + if (bus->dhd->dongle_reset) { + ret = BCME_NOTREADY; + goto done; +@@ -1779,7 +1555,7 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, + #endif /* WLMEDIA_HTSF */ + + /* Add alignment padding, allocate new packet if needed */ +- if ((pad1 = ((uintptr)frame % DHD_SDALIGN))) { ++ if (!((uintptr)frame & 1) && (pad1 = ((uintptr)frame % DHD_SDALIGN))) { + if (PKTHEADROOM(osh, pkt) < pad1) { + DHD_INFO(("%s: insufficient headroom %d for %d pad1\n", + __FUNCTION__, (int)PKTHEADROOM(osh, pkt), pad1)); +@@ -1819,8 +1595,7 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, + + #ifdef BCMSDIOH_TXGLOM + if (bus->glom_enable) { +- uint32 hwheader1 = 0, hwheader2 = 0; +- act_len = len; ++ uint32 hwheader1 = 0, hwheader2 = 0, act_len = len; + + /* Software tag: channel, sequence number, data offset */ + swheader = ((chan << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK) | +@@ -1830,9 +1605,8 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, + htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN + SDPCM_HWEXT_LEN + sizeof(swheader)); + + if (queue_only) { +- uint8 alignment = ALIGNMENT; +- if (forcealign && (len & (alignment - 1))) +- len = ROUNDUP(len, alignment); ++ if (forcealign && (len & (ALIGNMENT - 1))) ++ len = ROUNDUP(len, ALIGNMENT); + /* Hardware extention tag */ + /* 2byte frame length, 1byte-, 1byte frame flag, + * 2byte-hdrlength, 2byte padlenght +@@ -1841,25 +1615,8 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, + hwheader2 = (len - act_len) << 16; + htol32_ua_store(hwheader1, frame + SDPCM_FRAMETAG_LEN); + htol32_ua_store(hwheader2, frame + SDPCM_FRAMETAG_LEN + 4); +- real_pad = len - act_len; +- if (PKTTAILROOM(osh, pkt) < real_pad) { +- DHD_INFO(("%s 1: insufficient tailroom %d for %d real_pad\n", +- __FUNCTION__, (int)PKTTAILROOM(osh, pkt), real_pad)); +- if (PKTPADTAILROOM(osh, pkt, real_pad)) { +- DHD_ERROR(("CHK1: padding error size %d\n", real_pad)); +- ret = BCME_NOMEM; +- goto done; +- } +-#ifndef BCMLXSDMMC +- else +- PKTSETLEN(osh, pkt, act_len); +-#endif +- } +-#ifdef BCMLXSDMMC +- PKTSETLEN(osh, pkt, len); +-#endif /* BCMLXSDMMC */ + /* Post the frame pointer to sdio glom array */ +- dhd_bcmsdh_glom_post(bus, frame, pkt, len); ++ dhd_bcmsdh_glom_post(bus, frame, len); + /* Save the pkt pointer in bus glom array */ + bus->glom_pkt_arr[bus->glom_cnt] = pkt; + bus->glom_total_len += len; +@@ -1891,36 +1648,9 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, + hwheader2 = (len - act_len) << 16; + htol32_ua_store(hwheader1, frame + SDPCM_FRAMETAG_LEN); + htol32_ua_store(hwheader2, frame + SDPCM_FRAMETAG_LEN + 4); +- real_pad = len - act_len; +- if (PKTTAILROOM(osh, pkt) < real_pad) { +- DHD_INFO(("%s 2: insufficient tailroom %d" +- " for %d real_pad\n", +- __FUNCTION__, (int)PKTTAILROOM(osh, pkt), real_pad)); +- if (PKTPADTAILROOM(osh, pkt, real_pad)) { +- DHD_ERROR(("CHK2: padding error size %d." +- " %d more pkts are discarded together.\n", +- real_pad, bus->glom_cnt)); +- /* Save the pkt pointer in bus glom array +- * Otherwise, this last pkt will not be +- * cleaned under "goto done" +- */ +- bus->glom_pkt_arr[bus->glom_cnt] = pkt; +- bus->glom_cnt++; +- bus->glom_total_len += len; +- ret = BCME_NOMEM; +- goto done; +- } +-#ifndef BCMLXSDMMC +- else +- PKTSETLEN(osh, pkt, act_len); +-#endif +- } +-#ifdef BCMLXSDMMC +- PKTSETLEN(osh, pkt, len); +-#endif /* BCMLXSDMMC */ + + /* Post the frame pointer to sdio glom array */ +- dhd_bcmsdh_glom_post(bus, frame, pkt, len); ++ dhd_bcmsdh_glom_post(bus, frame, len); + /* Save the pkt pointer in bus glom array */ + bus->glom_pkt_arr[bus->glom_cnt] = pkt; + bus->glom_cnt++; +@@ -1934,7 +1664,6 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, + } else + #endif /* BCMSDIOH_TXGLOM */ + { +- act_len = len; + /* Software tag: channel, sequence number, data offset */ + swheader = ((chan << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK) | bus->tx_seq | + (((pad1 + SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK); +@@ -1977,24 +1706,8 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, + DHD_ERROR(("%s: sending unrounded %d-byte packet\n", __FUNCTION__, len)); + #endif + } +- real_pad = len - act_len; +- if (PKTTAILROOM(osh, pkt) < real_pad) { +- DHD_INFO(("%s 3: insufficient tailroom %d for %d real_pad\n", +- __FUNCTION__, (int)PKTTAILROOM(osh, pkt), real_pad)); +- if (PKTPADTAILROOM(osh, pkt, real_pad)) { +- DHD_ERROR(("CHK3: padding error size %d\n", real_pad)); +- ret = BCME_NOMEM; +- goto done; +- } +-#ifndef BCMLXSDMMC +- else +- PKTSETLEN(osh, pkt, act_len); +-#endif +- } +-#ifdef BCMLXSDMMC +- PKTSETLEN(osh, pkt, len); +-#endif /* BCMLXSDMMC */ + } ++ + do { + ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC, + frame, len, pkt, NULL, NULL); +@@ -2040,7 +1753,7 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, + done: + + #ifdef BCMSDIOH_TXGLOM +- if (bus->glom_enable && !queue_only) { ++ if (bus->glom_enable) { + dhd_bcmsdh_glom_clear(bus); + pkt_cnt = bus->glom_cnt; + } else +@@ -2053,33 +1766,20 @@ done: + #ifdef BCMSDIOH_TXGLOM + uint32 doff; + if (bus->glom_enable) { +-#ifdef BCMLXSDMMC +- uint32 pad2 = 0; +-#endif /* BCMLXSDMMC */ +- if (!queue_only) +- pkt = bus->glom_pkt_arr[bus->glom_cnt - pkt_cnt]; +- ++ pkt = bus->glom_pkt_arr[bus->glom_cnt - pkt_cnt]; + frame = (uint8*)PKTDATA(osh, pkt); + doff = ltoh32_ua(frame + SDPCM_FRAMETAG_LEN + SDPCM_HWEXT_LEN); + doff = (doff & SDPCM_DOFFSET_MASK) >> SDPCM_DOFFSET_SHIFT; +-#ifdef BCMLXSDMMC +- pad2 = ltoh32_ua(frame + SDPCM_FRAMETAG_LEN + 4) >> 16; +- PKTSETLEN(osh, pkt, PKTLEN(osh, pkt) - pad2); +-#endif /* BCMLXSDMMC */ + PKTPULL(osh, pkt, doff); + } else +-#endif /* BCMSDIOH_TXGLOM */ ++#endif + { +-#ifdef BCMLXSDMMC +- if (act_len > 0) +- PKTSETLEN(osh, pkt, act_len); +-#endif /* BCMLXSDMMC */ +- PKTPULL(osh, pkt, SDPCM_HDRLEN + pad1); ++ PKTPULL(osh, pkt, SDPCM_HDRLEN + pad1); + } + #ifdef PROP_TXSTATUS + if (bus->dhd->wlfc_state) { + dhd_os_sdunlock(bus->dhd); +- dhd_wlfc_txcomplete(bus->dhd, pkt, ret == 0); ++ dhd_wlfc_txcomplete(bus->dhd, pkt, ret == 0, FALSE); + dhd_os_sdlock(bus->dhd); + } else { + #endif /* PROP_TXSTATUS */ +@@ -2101,7 +1801,7 @@ done: + + #ifdef BCMSDIOH_TXGLOM + /* Reset the glom array */ +- if (bus->glom_enable && !queue_only) { ++ if (bus->glom_enable) { + bus->glom_cnt = 0; + bus->glom_total_len = 0; + } +@@ -2110,7 +1810,7 @@ done: + } + + int +-dhd_bus_txdata(struct dhd_bus *bus, void *pkt) ++dhd_bus_txdata(struct dhd_bus *bus, void *pkt, bool wlfc_locked) + { + int ret = BCME_ERROR; + osl_t *osh; +@@ -2195,7 +1895,7 @@ dhd_bus_txdata(struct dhd_bus *bus, void + #endif + #ifdef PROP_TXSTATUS + if (bus->dhd->wlfc_state) +- dhd_wlfc_txcomplete(bus->dhd, pkt, FALSE); ++ dhd_wlfc_txcomplete(bus->dhd, pkt, FALSE, wlfc_locked); + else + #endif + dhd_txcomplete(bus->dhd, pkt, FALSE); +@@ -2212,6 +1912,7 @@ dhd_bus_txdata(struct dhd_bus *bus, void + } + else + ret = BCME_OK; ++ dhd_os_sdunlock_txq(bus->dhd); + + if ((pktq_len(&bus->txq) >= FCHI) && dhd_doflow) + dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, ON); +@@ -2220,8 +1921,6 @@ dhd_bus_txdata(struct dhd_bus *bus, void + if (pktq_plen(&bus->txq, prec) > qcount[prec]) + qcount[prec] = pktq_plen(&bus->txq, prec); + #endif +- dhd_os_sdunlock_txq(bus->dhd); +- + /* Schedule DPC if needed to send queued packet(s) */ + if (dhd_deferred_tx && !bus->dpc_sched) { + bus->dpc_sched = TRUE; +@@ -2275,7 +1974,6 @@ dhdsdio_sendfromq(dhd_bus_t *bus, uint m + uint cnt = 0; + uint datalen; + uint8 tx_prec_map; +- uint16 txpktqlen = 0; + #ifdef BCMSDIOH_TXGLOM + uint i; + uint8 glom_cnt; +@@ -2297,36 +1995,28 @@ dhdsdio_sendfromq(dhd_bus_t *bus, uint m + for (cnt = 0; (cnt < maxframes) && DATAOK(bus); cnt++) { + #ifdef BCMSDIOH_TXGLOM + if (bus->glom_enable) { +- void *pkttable[SDPCM_MAXGLOM_SIZE]; +- dhd_os_sdlock_txq(bus->dhd); + glom_cnt = MIN(DATABUFCNT(bus), bus->glomsize); + glom_cnt = MIN(glom_cnt, pktq_mlen(&bus->txq, tx_prec_map)); + glom_cnt = MIN(glom_cnt, maxframes-cnt); + + /* Limiting the size to 2pkts in case of copy */ + if (bus->glom_mode == SDPCM_TXGLOM_CPY) +- glom_cnt = MIN(glom_cnt, 10); +- +- for (i = 0; i < glom_cnt; i++) +- pkttable[i] = pktq_mdeq(&bus->txq, tx_prec_map, &prec_out); +- +- txpktqlen = pktq_len(&bus->txq); +- dhd_os_sdunlock_txq(bus->dhd); ++ glom_cnt = MIN(glom_cnt, 5); + + if (glom_cnt == 0) + break; + datalen = 0; + for (i = 0; i < glom_cnt; i++) { +- uint datalen_tmp = 0; +- +- if ((pkt = pkttable[i]) == NULL) { ++ dhd_os_sdlock_txq(bus->dhd); ++ if ((pkt = pktq_mdeq(&bus->txq, tx_prec_map, &prec_out)) == NULL) { + /* This case should not happen */ + DHD_ERROR(("No pkts in the queue for glomming\n")); ++ dhd_os_sdunlock_txq(bus->dhd); + break; + } ++ dhd_os_sdunlock_txq(bus->dhd); + +- datalen_tmp = (PKTLEN(bus->dhd->osh, pkt) - SDPCM_HDRLEN); +- ++ datalen += (PKTLEN(bus->dhd->osh, pkt) - SDPCM_HDRLEN); + #ifndef SDTEST + ret = dhdsdio_txpkt(bus, + pkt, +@@ -2340,8 +2030,6 @@ dhdsdio_sendfromq(dhd_bus_t *bus, uint m + TRUE, + (i == (glom_cnt-1))? FALSE: TRUE); + #endif +- if (ret == BCME_OK) +- datalen += datalen_tmp; + } + cnt += i-1; + } else +@@ -2349,11 +2037,9 @@ dhdsdio_sendfromq(dhd_bus_t *bus, uint m + { + dhd_os_sdlock_txq(bus->dhd); + if ((pkt = pktq_mdeq(&bus->txq, tx_prec_map, &prec_out)) == NULL) { +- txpktqlen = pktq_len(&bus->txq); + dhd_os_sdunlock_txq(bus->dhd); + break; + } +- txpktqlen = pktq_len(&bus->txq); + dhd_os_sdunlock_txq(bus->dhd); + datalen = PKTLEN(bus->dhd->osh, pkt) - SDPCM_HDRLEN; + +@@ -2388,68 +2074,12 @@ dhdsdio_sendfromq(dhd_bus_t *bus, uint m + + /* Deflow-control stack if needed */ + if (dhd_doflow && dhd->up && (dhd->busstate == DHD_BUS_DATA) && +- dhd->txoff && (txpktqlen < FCLOW)) ++ dhd->txoff && (pktq_len(&bus->txq) < FCLOW)) + dhd_txflowcontrol(dhd, ALL_INTERFACES, OFF); + + return cnt; + } + +-static void +-dhdsdio_sendpendctl(dhd_bus_t *bus) +-{ +- bcmsdh_info_t *sdh = bus->sdh; +- int ret, i; +- uint8* frame_seq = bus->ctrl_frame_buf + SDPCM_FRAMETAG_LEN; +- +-#ifdef BCMSDIOH_TXGLOM +- if (bus->glom_enable) +- frame_seq += SDPCM_HWEXT_LEN; +-#endif +- +- if (*frame_seq != bus->tx_seq) { +- DHD_INFO(("%s IOCTL frame seq lag detected!" +- " frm_seq:%d != bus->tx_seq:%d, corrected\n", +- __FUNCTION__, *frame_seq, bus->tx_seq)); +- *frame_seq = bus->tx_seq; +- } +- +- ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC, +- (uint8 *)bus->ctrl_frame_buf, (uint32)bus->ctrl_frame_len, +- NULL, NULL, NULL); +- ASSERT(ret != BCME_PENDING); +- if (ret == BCME_NODEVICE) { +- DHD_ERROR(("%s: Device asleep already\n", __FUNCTION__)); +- } else if (ret < 0) { +- /* On failure, abort the command and terminate the frame */ +- DHD_INFO(("%s: sdio error %d, abort command and terminate frame.\n", +- __FUNCTION__, 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++) { +- uint8 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; +- } +- +- bus->ctrl_frame_stat = FALSE; +- dhd_wait_event_wakeup(bus->dhd); +-} +- + int + dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen) + { +@@ -2629,7 +2259,7 @@ done: + else + bus->dhd->tx_ctlpkts++; + +- if (bus->dhd->txcnt_timeout >= MAX_CNTL_TX_TIMEOUT) ++ if (bus->dhd->txcnt_timeout >= MAX_CNTL_TIMEOUT) + return -ETIMEDOUT; + + return ret ? -EIO : 0; +@@ -2658,7 +2288,7 @@ dhd_bus_rxctl(struct dhd_bus *bus, uchar + + if (rxlen) { + DHD_CTL(("%s: resumed on rxctl frame, got %d expected %d\n", +- __FUNCTION__, rxlen, msglen)); ++ __FUNCTION__, rxlen, msglen)); + } else if (timeleft == 0) { + #ifdef DHD_DEBUG + uint32 status, retry = 0; +@@ -2669,15 +2299,14 @@ dhd_bus_rxctl(struct dhd_bus *bus, uchar + DHD_ERROR(("%s: resumed on timeout\n", __FUNCTION__)); + #endif /* DHD_DEBUG */ + #ifdef DHD_DEBUG +- dhd_os_sdlock(bus->dhd); +- dhdsdio_checkdied(bus, NULL, 0); +- dhd_os_sdunlock(bus->dhd); ++ dhd_os_sdlock(bus->dhd); ++ dhdsdio_checkdied(bus, NULL, 0); ++ dhd_os_sdunlock(bus->dhd); + #endif /* DHD_DEBUG */ + } else if (pending == TRUE) { + /* signal pending */ + DHD_ERROR(("%s: signal pending\n", __FUNCTION__)); + return -EINTR; +- + } else { + DHD_CTL(("%s: resumed for unknown reason?\n", __FUNCTION__)); + #ifdef DHD_DEBUG +@@ -2687,10 +2316,8 @@ dhd_bus_rxctl(struct dhd_bus *bus, uchar + #endif /* DHD_DEBUG */ + } + if (timeleft == 0) { +- if (rxlen == 0) +- bus->dhd->rxcnt_timeout++; +- DHD_ERROR(("%s: rxcnt_timeout=%d, rxlen=%d\n", __FUNCTION__, +- bus->dhd->rxcnt_timeout, rxlen)); ++ bus->dhd->rxcnt_timeout++; ++ DHD_ERROR(("%s: rxcnt_timeout=%d\n", __FUNCTION__, bus->dhd->rxcnt_timeout)); + } + else + bus->dhd->rxcnt_timeout = 0; +@@ -2700,7 +2327,7 @@ dhd_bus_rxctl(struct dhd_bus *bus, uchar + else + bus->dhd->rx_ctlerrs++; + +- if (bus->dhd->rxcnt_timeout >= MAX_CNTL_RX_TIMEOUT) ++ if (bus->dhd->rxcnt_timeout >= MAX_CNTL_TIMEOUT) + return -ETIMEDOUT; + + if (bus->dhd->dongle_trap_occured) +@@ -2717,8 +2344,7 @@ enum { + IOV_SBREG, + IOV_SDCIS, + IOV_MEMBYTES, +- IOV_RAMSIZE, +- IOV_RAMSTART, ++ IOV_MEMSIZE, + #ifdef DHD_DEBUG + IOV_CHECKDIED, + IOV_SERIALCONS, +@@ -2758,8 +2384,7 @@ enum { + IOV_FWPATH, + #endif + IOV_TXGLOMSIZE, +- IOV_TXGLOMMODE, +- IOV_HANGREPORT ++ IOV_TXGLOMMODE + }; + + const bcm_iovar_t dhdsdio_iovars[] = { +@@ -2770,8 +2395,7 @@ const bcm_iovar_t dhdsdio_iovars[] = { + {"idleclock", IOV_IDLECLOCK, 0, IOVT_INT32, 0 }, + {"sd1idle", IOV_SD1IDLE, 0, IOVT_BOOL, 0 }, + {"membytes", IOV_MEMBYTES, 0, IOVT_BUFFER, 2 * sizeof(int) }, +- {"ramsize", IOV_RAMSIZE, 0, IOVT_UINT32, 0 }, +- {"ramstart", IOV_RAMSTART, 0, IOVT_UINT32, 0 }, ++ {"memsize", IOV_MEMSIZE, 0, IOVT_UINT32, 0 }, + {"dwnldstate", IOV_SET_DOWNLOAD_STATE, 0, IOVT_BOOL, 0 }, + {"socram_state", IOV_SOCRAM_STATE, 0, IOVT_BOOL, 0 }, + {"vars", IOV_VARS, 0, IOVT_BUFFER, 0 }, +@@ -2812,7 +2436,6 @@ const bcm_iovar_t dhdsdio_iovars[] = { + #endif + {"txglomsize", IOV_TXGLOMSIZE, 0, IOVT_UINT32, 0 }, + {"txglommode", IOV_TXGLOMMODE, 0, IOVT_UINT32, 0 }, +- {"fw_hang_report", IOV_HANGREPORT, 0, IOVT_BOOL, 0 }, + {NULL, 0, 0, 0, 0 } + }; + +@@ -2838,25 +2461,25 @@ dhd_bus_dump(dhd_pub_t *dhdp, struct bcm + 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 %u tx_seq %d, max %d, rxskip %d rxlen %u rx_seq %d\n", ++ 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 %u lastintrs %u spurious %u\n", ++ bcm_bprintf(strbuf, "intr %d intrcount %d lastintrs %d spurious %d\n", + bus->intr, bus->intrcount, bus->lastintrs, bus->spurious); +- bcm_bprintf(strbuf, "pollrate %u pollcnt %u regfails %u\n", ++ 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 %u fcqueued %u rxrtx %u rx_toolong %u rxc_errors %u\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 %u badhdr %u badseq %u\n", ++ 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 %u, fc_xoff %u, fc_xon %u\n", ++ 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 %u, rxglomframes %u, rxglompkts %u\n", ++ bcm_bprintf(strbuf, "rxglomfail %d, rxglomframes %d, rxglompkts %d\n", + bus->rxglomfail, bus->rxglomframes, bus->rxglompkts); +- bcm_bprintf(strbuf, "f2rx (hdrs/data) %u (%u/%u), f2tx %u f1regs %u\n", ++ 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); + { +@@ -2896,17 +2519,17 @@ dhd_bus_dump(dhd_pub_t *dhdp, struct bcm + #ifdef SDTEST + if (bus->pktgen_count) { + bcm_bprintf(strbuf, "pktgen config and count:\n"); +- bcm_bprintf(strbuf, "freq %u count %u print %u total %u min %u len %u\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 %u rcvd %u fail %u\n", ++ 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 %u roundup %u\n", bus->blocksize, bus->roundup); ++ 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); +@@ -3215,9 +2838,6 @@ dhdsdio_checkdied(dhd_bus_t *bus, char * + + DHD_TRACE(("%s: Enter\n", __FUNCTION__)); + +- if (DHD_NOCHECKDIED_ON()) +- return 0; +- + if (data == NULL) { + /* + * Called after a rx ctrl timeout. "data" is NULL. +@@ -3445,7 +3065,6 @@ dhd_serialconsole(dhd_bus_t *bus, bool s + uart_enab = CC_PLL_CHIPCTRL_SERIAL_ENAB; + } + else if (bus->sih->chip == BCM4334_CHIP_ID || +- bus->sih->chip == BCM43340_CHIP_ID || + bus->sih->chip == BCM43341_CHIP_ID) { + if (enable) { + /* Moved to PMU chipcontrol 1 from 4330 */ +@@ -3642,16 +3261,6 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bc + DHD_INFO(("%s: Request to %s %d bytes at address 0x%08x\n", __FUNCTION__, + (set ? "write" : "read"), size, address)); + +- /* check if CR4 */ +- if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) { +- /* +- * If address is start of RAM (i.e. a downloaded image), +- * store the reset instruction to be written in 0 +- */ +- if (address == bus->dongle_ram_base) { +- bus->resetinstr = *(((uint32*)params) + 2); +- } +- } else { + /* If we know about SOCRAM, check for a fit */ + if ((bus->orig_ramsize) && + ((address > bus->orig_ramsize) || (address + size > bus->orig_ramsize))) +@@ -3693,7 +3302,6 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bc + break; + } + } +- } + + /* Generate the actual data pointer */ + data = set ? (uint8*)params + 2 * sizeof(int): (uint8*)arg; +@@ -3704,16 +3312,11 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bc + break; + } + +- case IOV_GVAL(IOV_RAMSIZE): ++ case IOV_GVAL(IOV_MEMSIZE): + int_val = (int32)bus->ramsize; + bcopy(&int_val, arg, val_size); + break; + +- case IOV_GVAL(IOV_RAMSTART): +- int_val = (int32)bus->dongle_ram_base; +- bcopy(&int_val, arg, val_size); +- break; +- + case IOV_GVAL(IOV_SDIOD_DRIVE): + int_val = (int32)dhd_sdiod_drive_strength; + bcopy(&int_val, arg, val_size); +@@ -3951,14 +3554,13 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bc + case IOV_SVAL(IOV_MESBUSYCTRL): + mesbusyctrl = (uint)int_val; + mesbusyctrl = (mesbusyctrl > SBSDIO_MESBUSYCTRL_MASK) +- ? SBSDIO_MESBUSYCTRL_MASK : mesbusyctrl; ++ ? SBSDIO_MESBUSYCTRL_MASK : mesbusyctrl; + DHD_ERROR(("Setting mesbusyctrl as 0x%x.\n", mesbusyctrl)); + bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_MESBUSYCTRL, + ((uint8)mesbusyctrl | 0x80), NULL); + break; + #endif /* SDIO_CRC_ERROR_FIX */ + +- + case IOV_GVAL(IOV_DONGLEISOLATION): + int_val = bus->dhd->dongle_isolation; + bcopy(&int_val, arg, val_size); +@@ -4068,16 +3670,6 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bc + } + break; + #endif /* BCMSDIOH_TXGLOM */ +- +- case IOV_SVAL(IOV_HANGREPORT): +- bus->dhd->hang_report = bool_val; +- DHD_ERROR(("%s: Set hang_report as %d\n", __FUNCTION__, bus->dhd->hang_report)); +- break; +- +- case IOV_GVAL(IOV_HANGREPORT): +- int_val = (int32)bus->dhd->hang_report; +- bcopy(&int_val, arg, val_size); +- break; + default: + bcmerror = BCME_UNSUPPORTED; + break; +@@ -4198,8 +3790,6 @@ dhdsdio_download_state(dhd_bus_t *bus, b + int bcmerror = 0; + int foundcr4 = 0; + +- if (!bus->sih) +- return BCME_ERROR; + /* To enter download state, disable ARM and reset SOCRAM. + * To exit download state, simply reset ARM (default is RAM boot). + */ +@@ -4211,47 +3801,45 @@ dhdsdio_download_state(dhd_bus_t *bus, b + if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) { + foundcr4 = 1; + } else { +- DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__)); +- bcmerror = BCME_ERROR; +- goto fail; +- } ++ DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__)); ++ bcmerror = BCME_ERROR; ++ goto fail; ++ } + } + + if (!foundcr4) { +- si_core_disable(bus->sih, 0); +- if (bcmsdh_regfail(bus->sdh)) { +- bcmerror = BCME_SDIO_ERROR; +- goto fail; +- } ++ si_core_disable(bus->sih, 0); ++ if (bcmsdh_regfail(bus->sdh)) { ++ bcmerror = BCME_SDIO_ERROR; ++ goto fail; ++ } + +- if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) { +- DHD_ERROR(("%s: Failed to find SOCRAM core!\n", __FUNCTION__)); +- bcmerror = BCME_ERROR; +- goto fail; +- } ++ if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) { ++ DHD_ERROR(("%s: Failed to find SOCRAM core!\n", __FUNCTION__)); ++ bcmerror = BCME_ERROR; ++ goto fail; ++ } + +- si_core_reset(bus->sih, 0, 0); +- if (bcmsdh_regfail(bus->sdh)) { +- DHD_ERROR(("%s: Failure trying reset SOCRAM core?\n", +- __FUNCTION__)); ++ si_core_reset(bus->sih, 0, 0); ++ if (bcmsdh_regfail(bus->sdh)) { ++ DHD_ERROR(("%s: Failure trying reset SOCRAM core?\n", __FUNCTION__)); ++ bcmerror = BCME_SDIO_ERROR; ++ goto fail; ++ } ++ ++ /* Disable remap for download */ ++ if (REMAP_ENAB(bus) && si_socdevram_remap_isenb(bus->sih)) ++ dhdsdio_devram_remap(bus, FALSE); ++ ++ /* Clear the top bit of memory */ ++ if (bus->ramsize) { ++ uint32 zeros = 0; ++ if (dhdsdio_membytes(bus, TRUE, bus->ramsize - 4, (uint8*)&zeros, 4) < 0) { + bcmerror = BCME_SDIO_ERROR; + goto fail; + } +- +- /* Disable remap for download */ +- if (REMAP_ENAB(bus) && si_socdevram_remap_isenb(bus->sih)) +- dhdsdio_devram_remap(bus, FALSE); +- +- /* Clear the top bit of memory */ +- if (bus->ramsize) { +- uint32 zeros = 0; +- if (dhdsdio_membytes(bus, TRUE, bus->ramsize - 4, +- (uint8*)&zeros, 4) < 0) { +- bcmerror = BCME_SDIO_ERROR; +- goto fail; +- } +- } +- } else { ++ } ++ } else { + /* For CR4, + * Halt ARM + * Remove ARM reset +@@ -4265,44 +3853,44 @@ dhdsdio_download_state(dhd_bus_t *bus, b + } + } else { + if (!si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) { +- if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) { +- DHD_ERROR(("%s: Failed to find SOCRAM core!\n", __FUNCTION__)); +- bcmerror = BCME_ERROR; +- goto fail; +- } ++ if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) { ++ DHD_ERROR(("%s: Failed to find SOCRAM core!\n", __FUNCTION__)); ++ bcmerror = BCME_ERROR; ++ goto fail; ++ } + +- if (!si_iscoreup(bus->sih)) { +- DHD_ERROR(("%s: SOCRAM core is down after reset?\n", __FUNCTION__)); +- bcmerror = BCME_ERROR; +- goto fail; +- } ++ if (!si_iscoreup(bus->sih)) { ++ DHD_ERROR(("%s: SOCRAM core is down after reset?\n", __FUNCTION__)); ++ bcmerror = BCME_ERROR; ++ goto fail; ++ } + +- if ((bcmerror = dhdsdio_write_vars(bus))) { +- DHD_ERROR(("%s: could not write vars to RAM\n", __FUNCTION__)); +- goto fail; +- } ++ if ((bcmerror = dhdsdio_write_vars(bus))) { ++ DHD_ERROR(("%s: could not write vars to RAM\n", __FUNCTION__)); ++ goto fail; ++ } + +- /* Enable remap before ARM reset but after vars. +- * No backplane access in remap mode +- */ +- if (REMAP_ENAB(bus) && !si_socdevram_remap_isenb(bus->sih)) +- dhdsdio_devram_remap(bus, TRUE); ++ /* Enable remap before ARM reset but after vars. ++ * No backplane access in remap mode ++ */ ++ if (REMAP_ENAB(bus) && !si_socdevram_remap_isenb(bus->sih)) ++ dhdsdio_devram_remap(bus, TRUE); + +- if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0) && +- !si_setcore(bus->sih, SDIOD_CORE_ID, 0)) { +- DHD_ERROR(("%s: Can't change back to SDIO core?\n", __FUNCTION__)); +- bcmerror = BCME_ERROR; +- goto fail; +- } +- W_SDREG(0xFFFFFFFF, &bus->regs->intstatus, retries); ++ if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0) && ++ !si_setcore(bus->sih, SDIOD_CORE_ID, 0)) { ++ DHD_ERROR(("%s: Can't change back to SDIO core?\n", __FUNCTION__)); ++ bcmerror = BCME_ERROR; ++ goto fail; ++ } ++ W_SDREG(0xFFFFFFFF, &bus->regs->intstatus, retries); + + +- if (!(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) && +- !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) { +- DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__)); +- bcmerror = BCME_ERROR; +- goto fail; +- } ++ if (!(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) && ++ !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) { ++ DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__)); ++ bcmerror = BCME_ERROR; ++ goto fail; ++ } + } else { + /* cr4 has no socram, but tcm's */ + /* write vars */ +@@ -4419,10 +4007,6 @@ dhd_bus_iovar_op(dhd_pub_t *dhdp, const + } else { + DHD_INFO(("%s: noted %s update, value now %d\n", + __FUNCTION__, "sd_blocksize", bus->blocksize)); +- +- if ((bus->sih->chip == BCM4335_CHIP_ID) || +- (bus->sih->chip == BCM4339_CHIP_ID)) +- dhd_overflow_war(bus); + } + } + bus->roundup = MIN(max_roundup, bus->blocksize); +@@ -4467,7 +4051,7 @@ dhd_bus_stop(struct dhd_bus *bus, bool e + { + osl_t *osh; + uint32 local_hostintmask; +- uint8 saveclk; ++ uint8 saveclk, dat; + uint retries; + int err; + if (!bus->dhd) +@@ -4487,40 +4071,45 @@ dhd_bus_stop(struct dhd_bus *bus, bool e + bus->hostintmask = 0; + bcmsdh_intr_disable(bus->sdh); + } else { +- + BUS_WAKE(bus); + ++ if (KSO_ENAB(bus)) { ++ /* Mask the interrupt */ ++ dat = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_INTEN, NULL); ++ dat &= ~(INTR_CTL_FUNC1_EN | INTR_CTL_FUNC2_EN); ++ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_INTEN, dat, NULL); ++ } ++ + /* Change our idea of bus state */ + bus->dhd->busstate = DHD_BUS_DOWN; + + if (KSO_ENAB(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; ++ /* Enable clock for device interrupts */ ++ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); + +- /* 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", +- __FUNCTION__, err)); +- } ++ /* Disable and clear interrupts at the chip level also */ ++ W_SDREG(0, &bus->regs->hostintmask, retries); ++ local_hostintmask = bus->hostintmask; ++ bus->hostintmask = 0; ++ ++ /* 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", __FUNCTION__, err)); ++ } + +- /* Turn off the bus (F2), free any pending packets */ +- DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__)); +- bcmsdh_intr_disable(bus->sdh); +- bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1, NULL); ++ /* Turn off the bus (F2), free any pending packets */ ++ DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__)); ++ 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); ++ /* Clear any pending interrupts now that F2 is disabled */ ++ W_SDREG(local_hostintmask, &bus->regs->intstatus, retries); + } + + /* Turn off the backplane clock (only) */ +@@ -4547,8 +4136,6 @@ dhd_bus_stop(struct dhd_bus *bus, bool e + bus->rxskip = FALSE; + bus->tx_seq = bus->rx_seq = 0; + +- bus->tx_max = 4; +- + if (enforce_mutex) + dhd_os_sdunlock(bus->dhd); + } +@@ -4563,8 +4150,6 @@ dhd_txglom_enable(dhd_pub_t *dhdp, bool + uint32 rxglom; + int32 ret; + +- DHD_TRACE(("%s: Enter\n", __FUNCTION__)); +- + if (enable) { + rxglom = 1; + memset(buf, 0, sizeof(buf)); +@@ -4662,11 +4247,8 @@ dhd_bus_init(dhd_pub_t *dhdp, bool enfor + mesbusyctrl = watermark = bus->blocksize / 4; + } + #endif /* SDIO_CRC_ERROR_FIX */ +- if (!((bus->sih->chip == BCM4335_CHIP_ID) || +- (bus->sih->chip == BCM4339_CHIP_ID))) { +- bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, +- (uint8)watermark, &err); +- } ++ ++ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, (uint8)watermark, &err); + #ifdef SDIO_CRC_ERROR_FIX + bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_MESBUSYCTRL, + (uint8)mesbusyctrl|0x80, &err); +@@ -4697,14 +4279,8 @@ dhd_bus_init(dhd_pub_t *dhdp, bool enfor + bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, enable, NULL); + } + +- if (dhdsdio_sr_cap(bus)) { ++ if (dhdsdio_sr_cap(bus)) + dhdsdio_sr_init(bus); +- /* Masking the chip active interrupt permanantly */ +- bus->hostintmask &= ~I_CHIPACTIVE; +- W_SDREG(bus->hostintmask, &bus->regs->hostintmask, retries); +- DHD_INFO(("%s: disable I_CHIPACTIVE in hostintmask[0x%08x]\n", +- __FUNCTION__, bus->hostintmask)); +- } + else + bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, + SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err); +@@ -4743,21 +4319,12 @@ dhdsdio_rxfail(dhd_bus_t *bus, bool abor + } + + bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL, SFC_RF_TERM, &err); +- if (err) { +- DHD_ERROR(("%s: SBSDIO_FUNC1_FRAMECTRL cmd err\n", __FUNCTION__)); +- goto fail; +- } + 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, &err); +- if (err) { +- DHD_ERROR(("%s: SBSDIO_FUNC1_RFAMEBCLO cmd err\n", __FUNCTION__)); +- goto fail; +- } +- ++ lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCLO, NULL); + bus->f1regdata += 2; + + if ((hi == 0) && (lo == 0)) +@@ -4788,7 +4355,6 @@ dhdsdio_rxfail(dhd_bus_t *bus, bool abor + /* Clear partial in any case */ + bus->nextlen = 0; + +-fail: + /* If we can't reach the device, signal failure */ + if (err || bcmsdh_regfail(sdh)) + bus->dhd->busstate = DHD_BUS_DOWN; +@@ -4893,9 +4459,6 @@ done: + /* Awake any waiters */ + dhd_os_ioctl_resp_wake(bus->dhd); + } +-int +-dhd_process_pkt_reorder_info(dhd_pub_t *dhd, uchar *reorder_info_buf, uint reorder_info_len, +- void **pkt, uint32 *pkt_count); + + static uint8 + dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq) +@@ -5266,11 +4829,14 @@ dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxs + temp = PKTNEXT(osh, temp); + } + pfirst = temp; +- if (list_tail[ifidx] == NULL) ++ if (list_tail[ifidx] == NULL) { + list_head[ifidx] = ppfirst; +- else ++ list_tail[ifidx] = pfirst; ++ } ++ else { + PKTSETNEXT(osh, list_tail[ifidx], ppfirst); +- list_tail[ifidx] = pfirst; ++ list_tail[ifidx] = pfirst; ++ } + } + + num += (uint8)free_buf_count; +@@ -5383,13 +4949,14 @@ dhdsdio_readframes(dhd_bus_t *bus, uint + rxseq++, rxleft--) { + + #ifdef DHDTHREAD +- /* tx more to improve rx performance */ +- if (TXCTLOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL)) { +- dhdsdio_sendpendctl(bus); +- } else if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate && +- pktq_mlen(&bus->txq, ~bus->flowcontrol) && DATAOK(bus)) { +- dhdsdio_sendfromq(bus, dhd_txbound); +- } ++ /* terence: fix got unlikely tx max for 43362a0*/ ++ if (bus->sih->chip!=BCM43362_CHIP_ID && bus->sih->chiprev!=BCM43362A0_CHIP_REV) { ++ /* tx more to improve rx performance */ ++ if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate && ++ pktq_mlen(&bus->txq, ~bus->flowcontrol) && DATAOK(bus)) { ++ dhdsdio_sendfromq(bus, dhd_txbound); ++ } ++ } + #endif /* DHDTHREAD */ + + /* Handle glomming separately */ +@@ -5912,6 +5479,7 @@ deliver: + else + pkt_count = 1; + ++ + /* Unlock during rx call */ + dhd_os_sdunlock(bus->dhd); + dhd_rx_frame(bus->dhd, ifidx, pkt, pkt_count, chan); +@@ -6239,14 +5807,57 @@ clkwait: + resched = TRUE; + } + #endif /* defined(OOB_INTR_ONLY) && !defined(HW_OOB) */ +- + #ifdef PROP_TXSTATUS + dhd_wlfc_trigger_pktcommit(bus->dhd); + #endif ++ if (TXCTLOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL)) { ++ int ret, i; ++ ++ uint8* frame_seq = bus->ctrl_frame_buf + SDPCM_FRAMETAG_LEN; ++ ++ if (*frame_seq != bus->tx_seq) { ++ DHD_INFO(("%s IOCTL frame seq lag detected!" ++ " frm_seq:%d != bus->tx_seq:%d, corrected\n", ++ __FUNCTION__, *frame_seq, bus->tx_seq)); ++ *frame_seq = bus->tx_seq; ++ } ++ ++ ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC, ++ (uint8 *)bus->ctrl_frame_buf, (uint32)bus->ctrl_frame_len, ++ NULL, NULL, NULL); ++ ASSERT(ret != BCME_PENDING); ++ if (ret == BCME_NODEVICE) { ++ DHD_ERROR(("%s: Device asleep already\n", __FUNCTION__)); ++ } else if (ret < 0) { ++ /* On failure, abort the command and terminate the frame */ ++ DHD_INFO(("%s: sdio error %d, abort command and terminate frame.\n", ++ __FUNCTION__, ret)); ++ bus->tx_sderrs++; ++ ++ bcmsdh_abort(sdh, SDIO_FUNC_2); + +- if (TXCTLOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL)) +- dhdsdio_sendpendctl(bus); ++ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL, ++ SFC_WF_TERM, NULL); ++ bus->f1regdata++; + ++ for (i = 0; i < 3; i++) { ++ uint8 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; ++ } ++ ++ 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 && + pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit && DATAOK(bus)) { +@@ -6289,13 +5900,6 @@ clkwait: + } + + exit: +- +- if (!resched && dhd_dpcpoll) { +- if (dhdsdio_readframes(bus, dhd_rxbound, &rxdone) != 0) { +- resched = TRUE; +- } +- } +- + dhd_os_sdunlock(bus->dhd); + return resched; + } +@@ -6360,13 +5964,11 @@ dhdsdio_isr(void *arg) + #if defined(SDIO_ISR_THREAD) + DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __FUNCTION__)); + DHD_OS_WAKE_LOCK(bus->dhd); +- dhdsdio_dpc(bus); ++ while (dhdsdio_dpc(bus)); + DHD_OS_WAKE_UNLOCK(bus->dhd); + #else +- + bus->dpc_sched = TRUE; + dhd_sched_dpc(bus->dhd); +- + #endif + + } +@@ -6387,7 +5989,7 @@ dhdsdio_pktgen_init(dhd_bus_t *bus) + + /* Default to per-watchdog burst with 10s print time */ + bus->pktgen_freq = 1; +- bus->pktgen_print = dhd_watchdog_ms ? (10000 / dhd_watchdog_ms) : 0; ++ bus->pktgen_print = dhd_watchdog_ms ? (10000/dhd_watchdog_ms):0; + bus->pktgen_count = (dhd_pktgen * dhd_watchdog_ms + 999) / 1000; + + /* Default to echo mode */ +@@ -6772,8 +6374,9 @@ dhd_bus_watchdog(dhd_pub_t *dhdp) + else { + bus->idlecount++; + +- if ((bus->idletime > 0) && (bus->idlecount >= bus->idletime)) { ++ if (bus->idlecount >= bus->idletime) { + DHD_TIMER(("%s: DHD Idle state!!\n", __FUNCTION__)); ++ + if (SLPAUTO_ENAB(bus)) { + if (dhdsdio_bussleep(bus, TRUE) != BCME_BUSY) + dhd_os_wd_timer(bus->dhd, 0); +@@ -6918,28 +6521,16 @@ dhdsdio_chipmatch(uint16 chipid) + return TRUE; + if (chipid == BCM4314_CHIP_ID) + return TRUE; +- if (chipid == BCM43242_CHIP_ID) +- return TRUE; +- if (chipid == BCM43340_CHIP_ID) ++ if (chipid == BCM4334_CHIP_ID) + return TRUE; + if (chipid == BCM43341_CHIP_ID) + return TRUE; +- if (chipid == BCM43143_CHIP_ID) +- return TRUE; +- if (chipid == BCM43342_CHIP_ID) +- return TRUE; +- if (chipid == BCM4334_CHIP_ID) +- return TRUE; + if (chipid == BCM43239_CHIP_ID) + return TRUE; + if (chipid == BCM4324_CHIP_ID) + return TRUE; + if (chipid == BCM4335_CHIP_ID) + return TRUE; +- if (chipid == BCM4339_CHIP_ID) +- return TRUE; +- if (chipid == BCM4350_CHIP_ID) +- return TRUE; + return FALSE; + } + +@@ -6953,6 +6544,16 @@ dhdsdio_probe(uint16 venid, uint16 devid + struct ether_addr ea_addr; + #endif /* GET_CUSTOM_MAC_ENABLE */ + ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) ++ ++ if (mutex_is_locked(&_dhd_sdio_mutex_lock_) == 0) { ++ DHD_ERROR(("%s : no mutex held. set lock\n", __FUNCTION__)); ++ } ++ else { ++ DHD_ERROR(("%s : mutex is locked!. wait for unlocking\n", __FUNCTION__)); ++ } ++ mutex_lock(&_dhd_sdio_mutex_lock_); ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */ + + /* Init global variables at run-time, not as part of the declaration. + * This is required to support init/de-init of the driver. Initialization +@@ -6966,8 +6567,8 @@ dhdsdio_probe(uint16 venid, uint16 devid + sd1idle = TRUE; + dhd_readahead = TRUE; + retrydata = FALSE; +- dhd_doflow = TRUE; +- dhd_dongle_ramsize = 0; ++ dhd_doflow = FALSE; ++ dhd_dongle_memsize = 0; + dhd_txminmax = DHD_TXMINMAX; + + forcealign = TRUE; +@@ -7100,11 +6701,10 @@ dhdsdio_probe(uint16 venid, uint16 devid + #endif /* GET_CUSTOM_MAC_ENABLE */ + + /* if firmware path present try to download and bring up bus */ +- bus->dhd->hang_report = TRUE; + if (dhd_download_fw_on_driverload) { + if ((ret = dhd_bus_start(bus->dhd)) != 0) { + DHD_ERROR(("%s: dhd_bus_start failed\n", __FUNCTION__)); +- goto fail; ++ goto fail; + } + } + /* Ok, have the per-port tell the stack we're open for business */ +@@ -7113,7 +6713,10 @@ dhdsdio_probe(uint16 venid, uint16 devid + goto fail; + } + +- ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) ++ mutex_unlock(&_dhd_sdio_mutex_lock_); ++ DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__)); ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ + + return bus; + +@@ -7121,6 +6724,10 @@ fail: + dhdsdio_release(bus, osh); + + forcereturn: ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) ++ mutex_unlock(&_dhd_sdio_mutex_lock_); ++ DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__)); ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ + + return NULL; + } +@@ -7140,6 +6747,12 @@ dhdsdio_probe_attach(struct dhd_bus *bus + DHD_ERROR(("%s: FAILED to return to SI_ENUM_BASE\n", __FUNCTION__)); + } + ++#ifdef DHD_DEBUG ++ DHD_ERROR(("F1 signature read @0x18000000=0x%4x\n", ++ bcmsdh_reg_read(bus->sdh, SI_ENUM_BASE, 4))); ++ ++#endif /* DHD_DEBUG */ ++ + + /* Force PLL off until si_attach() programs PLL control regs */ + +@@ -7208,14 +6821,6 @@ dhdsdio_probe_attach(struct dhd_bus *bus + goto fail; + } + +- +-#ifdef DHD_DEBUG +- DHD_ERROR(("F1 signature OK, socitype:0x%x chip:0x%4x rev:0x%x pkg:0x%x\n", +- bus->sih->socitype, bus->sih->chip, bus->sih->chiprev, +- bus->sih->chippkg)); +-#endif /* DHD_DEBUG */ +- +- + bcmsdh_chipinfo(sdh, bus->sih->chip, bus->sih->chiprev); + + if (!dhdsdio_chipmatch((uint16)bus->sih->chip)) { +@@ -7247,10 +6852,10 @@ dhdsdio_probe_attach(struct dhd_bus *bus + } + + if (!si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) { +- if (!(bus->orig_ramsize = si_socram_size(bus->sih))) { +- DHD_ERROR(("%s: failed to find SOCRAM memory!\n", __FUNCTION__)); +- goto fail; +- } ++ if (!(bus->orig_ramsize = si_socram_size(bus->sih))) { ++ DHD_ERROR(("%s: failed to find SOCRAM memory!\n", __FUNCTION__)); ++ goto fail; ++ } + } else { + /* cr4 has a different way to find the RAM size from TCM's */ + if (!(bus->orig_ramsize = si_tcm_size(bus->sih))) { +@@ -7258,29 +6863,14 @@ dhdsdio_probe_attach(struct dhd_bus *bus + goto fail; + } + /* also populate base address */ +- switch ((uint16)bus->sih->chip) { +- case BCM4335_CHIP_ID: +- case BCM4339_CHIP_ID: +- bus->dongle_ram_base = CR4_4335_RAM_BASE; +- break; +- case BCM4350_CHIP_ID: +- bus->dongle_ram_base = CR4_4350_RAM_BASE; +- break; +- case BCM4360_CHIP_ID: +- bus->dongle_ram_base = CR4_4360_RAM_BASE; +- break; +- default: +- bus->dongle_ram_base = 0; +- DHD_ERROR(("%s: WARNING: Using default ram base at 0x%x\n", +- __FUNCTION__, bus->dongle_ram_base)); +- } ++ bus->dongle_ram_base = CR4_RAM_BASE; + } + bus->ramsize = bus->orig_ramsize; +- if (dhd_dongle_ramsize) +- dhd_dongle_setramsize(bus, dhd_dongle_ramsize); ++ if (dhd_dongle_memsize) ++ dhd_dongle_setmemsize(bus, dhd_dongle_memsize); + +- DHD_ERROR(("DHD: dongle ram size is set to %d(orig %d) at 0x%x\n", +- bus->ramsize, bus->orig_ramsize, bus->dongle_ram_base)); ++ DHD_ERROR(("DHD: dongle ram size is set to %d(orig %d)\n", ++ bus->ramsize, bus->orig_ramsize)); + + bus->srmemsize = si_socram_srmem_size(bus->sih); + } +@@ -7321,7 +6911,7 @@ dhdsdio_probe_attach(struct dhd_bus *bus + + #ifdef BCMSDIOH_TXGLOM + /* Setting default Glom mode */ +- bus->glom_mode = bcmsdh_set_mode(bus->sdh, SDPCM_DEFGLOM_MODE); ++ bus->glom_mode = SDPCM_TXGLOM_CPY; + /* Setting default Glom size */ + bus->glomsize = SDPCM_DEFGLOM_SIZE; + #endif +@@ -7427,10 +7017,6 @@ dhdsdio_probe_init(dhd_bus_t *bus, osl_t + } else { + DHD_INFO(("%s: Initial value for %s is %d\n", + __FUNCTION__, "sd_blocksize", bus->blocksize)); +- +- if ((bus->sih->chip == BCM4335_CHIP_ID) || +- (bus->sih->chip == BCM4339_CHIP_ID)) +- dhd_overflow_war(bus); + } + bus->roundup = MIN(max_roundup, bus->blocksize); + +@@ -7447,6 +7033,81 @@ dhdsdio_probe_init(dhd_bus_t *bus, osl_t + return TRUE; + } + ++void ++dhd_bus_select_firmware_name_by_chip(struct dhd_bus *bus, char *dst, char *src) ++{ ++ int fw_type, ag_type; ++ static uint chip, chiprev, first=1; ++ int i; ++ ++ if (first) { ++ chip = bus->sih->chip; ++ chiprev = bus->sih->chiprev; ++ first = 0; ++ } ++ if (src[0] == '\0') { ++#ifdef CONFIG_BCMDHD_FW_PATH ++ bcm_strncpy_s(src, sizeof(fw_path), CONFIG_BCMDHD_FW_PATH, MOD_PARAM_PATHLEN-1); ++ if (src[0] == '\0') ++#endif ++ { ++ printf("src firmware path is null\n"); ++ return; ++ } ++ } ++ ++ strcpy(dst, src); ++#ifndef FW_PATH_AUTO_SELECT ++ return; ++#endif ++ ++ /* find out the last '/' */ ++ i = strlen(dst); ++ while (i>0){ ++ if (dst[i] == '/') break; ++ i--; ++ } ++#ifdef BAND_AG ++ ag_type = FW_TYPE_AG; ++#else ++ ag_type = strstr(&dst[i], "_ag") ? FW_TYPE_AG : FW_TYPE_G; ++#endif ++ fw_type = (strstr(&dst[i], "_mfg") ? ++ FW_TYPE_MFG : (strstr(&dst[i], "_apsta") ? ++ FW_TYPE_APSTA : (strstr(&dst[i], "_p2p") ? ++ FW_TYPE_P2P : FW_TYPE_STA))); ++ ++ ++ switch (chip) { ++ case BCM4330_CHIP_ID: ++ if (ag_type == FW_TYPE_G) { ++ if (chiprev == BCM4330B2_CHIP_REV) ++ strcpy(&dst[i+1], bcm40183b2_fw_name[fw_type]); ++ break; ++ } else { ++ if (chiprev == BCM4330B2_CHIP_REV) ++ strcpy(&dst[i+1], bcm40183b2ag_fw_name[fw_type]); ++ break; ++ } ++ case BCM43362_CHIP_ID: ++ if (chiprev == BCM43362A0_CHIP_REV) ++ strcpy(&dst[i+1], bcm40181a0_fw_name[fw_type]); ++ else ++ strcpy(&dst[i+1], bcm40181a2_fw_name[fw_type]); ++ break; ++ case BCM43341_CHIP_ID: ++ if (chiprev == BCM43341B0_CHIP_REV) ++ strcpy(&dst[i+1], bcm43341b0ag_fw_name[fw_type]); ++ break; ++ case BCM4324_CHIP_ID: ++ if (chiprev == BCM43241B4_CHIP_REV) ++ strcpy(&dst[i+1], bcm43241b4ag_fw_name[fw_type]); ++ break; ++ } ++ ++ printf("%s: firmware_path=%s\n", __FUNCTION__, dst); ++} ++ + bool + dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh, + char *pfw_path, char *pnv_path) +@@ -7471,6 +7132,8 @@ dhdsdio_download_firmware(struct dhd_bus + /* Download the firmware */ + dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); + ++ printk("Final fw_path=%s\n", bus->fw_path); ++ printk("Final nv_path=%s\n", bus->nv_path); + ret = _dhdsdio_download_firmware(bus) == 0; + + dhdsdio_clkctl(bus, CLK_SDONLY, FALSE); +@@ -7586,16 +7249,28 @@ dhdsdio_disconnect(void *ptr) + { + dhd_bus_t *bus = (dhd_bus_t *)ptr; + +- DHD_TRACE(("%s: Enter\n", __FUNCTION__)); ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) + ++ if (mutex_is_locked(&_dhd_sdio_mutex_lock_) == 0) { ++ DHD_ERROR(("%s : no mutex held. set lock\n", __FUNCTION__)); ++ } ++ else { ++ DHD_ERROR(("%s : mutex is locked!. wait for unlocking\n", __FUNCTION__)); ++ } ++ mutex_lock(&_dhd_sdio_mutex_lock_); ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */ + ++ DHD_TRACE(("%s: Enter\n", __FUNCTION__)); + + if (bus) { + ASSERT(bus->dhd); + dhdsdio_release(bus, bus->dhd->osh); + } + +- ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) ++ mutex_unlock(&_dhd_sdio_mutex_lock_); ++ DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__)); ++#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */ + + DHD_TRACE(("%s: Disconnected\n", __FUNCTION__)); + } +@@ -7652,17 +7327,6 @@ dhdsdio_download_code_array(struct dhd_b + + /* Download image */ + while ((offset + MEMBLOCK) < sizeof(dlarray)) { +- /* check if CR4 */ +- if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) { +- /* if address is 0, store the reset instruction to be written in 0 */ +- +- if (offset == 0) { +- bus->resetinstr = *(((uint32*)dlarray)); +- /* Add start of RAM address to the address given by user */ +- offset += bus->dongle_ram_base; +- } +- } +- + bcmerror = dhdsdio_membytes(bus, TRUE, offset, + (uint8 *) (dlarray + offset), MEMBLOCK); + if (bcmerror) { +@@ -7738,6 +7402,7 @@ dhdsdio_download_code_file(struct dhd_bu + int len; + void *image = NULL; + uint8 *memblock = NULL, *memptr; ++ uint8 *memptr_tmp = NULL; // terence: check downloaded firmware is correct + + DHD_INFO(("%s: download firmware %s\n", __FUNCTION__, pfw_path)); + +@@ -7750,6 +7415,13 @@ dhdsdio_download_code_file(struct dhd_bu + DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__, MEMBLOCK)); + goto err; + } ++ if (dhd_msg_level & DHD_TRACE_VAL) { ++ memptr_tmp = MALLOC(bus->dhd->osh, MEMBLOCK + DHD_SDALIGN); ++ if (memptr_tmp == NULL) { ++ DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__, MEMBLOCK)); ++ goto err; ++ } ++ } + if ((uint32)(uintptr)memblock % DHD_SDALIGN) + memptr += (DHD_SDALIGN - ((uint32)(uintptr)memblock % DHD_SDALIGN)); + +@@ -7760,17 +7432,6 @@ dhdsdio_download_code_file(struct dhd_bu + bcmerror = BCME_ERROR; + goto err; + } +- /* check if CR4 */ +- if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) { +- /* if address is 0, store the reset instruction to be written in 0 */ +- +- if (offset == 0) { +- bus->resetinstr = *(((uint32*)memptr)); +- /* Add start of RAM address to the address given by user */ +- offset += bus->dongle_ram_base; +- } +- } +- + bcmerror = dhdsdio_membytes(bus, TRUE, offset, memptr, len); + if (bcmerror) { + DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n", +@@ -7778,12 +7439,29 @@ dhdsdio_download_code_file(struct dhd_bu + goto err; + } + ++ if (dhd_msg_level & DHD_TRACE_VAL) { ++ bcmerror = dhdsdio_membytes(bus, FALSE, offset, memptr_tmp, len); ++ if (bcmerror) { ++ DHD_ERROR(("%s: error %d on reading %d membytes at 0x%08x\n", ++ __FUNCTION__, bcmerror, MEMBLOCK, offset)); ++ goto err; ++ } ++ if (memcmp(memptr_tmp, memptr, len)) { ++ DHD_ERROR(("%s: Downloaded image is corrupted.\n", __FUNCTION__)); ++ goto err; ++ } else ++ DHD_INFO(("%s: Download, Upload and compare succeeded.\n", __FUNCTION__)); ++ } + offset += MEMBLOCK; + } + + err: + if (memblock) + MFREE(bus->dhd->osh, memblock, MEMBLOCK + DHD_SDALIGN); ++ if (dhd_msg_level & DHD_TRACE_VAL) { ++ if (memptr_tmp) ++ MFREE(bus->dhd->osh, memptr_tmp, MEMBLOCK + DHD_SDALIGN); ++ } + + if (image) + dhd_os_close_image(image); +@@ -7920,7 +7598,6 @@ _dhdsdio_download_firmware(struct dhd_bu + dlok = TRUE; + } + } +- + #ifdef BCMEMBEDIMAGE + if (embed) { + if (dhdsdio_download_code_array(bus)) { +@@ -7991,9 +7668,9 @@ dhd_bcmsdh_send_buf(dhd_bus_t *bus, uint + + #ifdef BCMSDIOH_TXGLOM + static void +-dhd_bcmsdh_glom_post(dhd_bus_t *bus, uint8 *frame, void *pkt, uint len) ++dhd_bcmsdh_glom_post(dhd_bus_t *bus, uint8 *frame, uint len) + { +- bcmsdh_glom_post(bus->sdh, frame, pkt, len); ++ bcmsdh_glom_post(bus->sdh, frame, len); + } + + static void +@@ -8063,14 +7740,14 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8 + #endif + dhd_os_sdunlock(dhdp); + +- DHD_TRACE(("%s: WLAN OFF DONE\n", __FUNCTION__)); ++ DHD_ERROR(("%s: WLAN OFF DONE\n", __FUNCTION__)); + /* App can now remove power from device */ + } else + bcmerror = BCME_SDIO_ERROR; + } else { + /* App must have restored power to device before calling */ + +- DHD_TRACE(("\n\n%s: == WLAN ON ==\n", __FUNCTION__)); ++ DHD_ERROR(("\n\n%s: == WLAN ON ==\n", __FUNCTION__)); + + if (bus->dhd->dongle_reset) { + /* Turn on WLAN */ +@@ -8085,6 +7762,7 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8 + (uint32 *)SI_ENUM_BASE, + bus->cl_devid)) { + /* Attempt to download binary to the dongle */ ++ COPY_FW_PATH_BY_CHIP(bus, fw_path, firmware_path); // terence + if (dhdsdio_probe_init(bus, bus->dhd->osh, bus->sdh) && + dhdsdio_download_firmware(bus, bus->dhd->osh, bus->sdh)) { + +@@ -8092,13 +7770,6 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8 + bcmerror = dhd_bus_init((dhd_pub_t *) bus->dhd, FALSE); + if (bcmerror == BCME_OK) { + #if defined(OOB_INTR_ONLY) +- /* make sure oob intr get registered */ +- if (!bcmsdh_is_oob_intr_registered()) { +- sdioh_start(NULL, 1); +- bcmsdh_register_oob_intr(dhdp); +- dhdp->iswl = TRUE; +- } +- + bcmsdh_set_irq(TRUE); + dhd_enable_oob_intr(bus, TRUE); + #endif +@@ -8111,7 +7782,13 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8 + dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF); + #endif + dhd_os_wd_timer(dhdp, dhd_watchdog_ms); +- DHD_TRACE(("%s: WLAN ON DONE\n", __FUNCTION__)); ++#ifdef BCMSDIOH_TXGLOM ++ if ((dhdp->busstate == DHD_BUS_DATA) && ++ bcmsdh_glom_enabled()) { ++ dhd_txglom_enable(dhdp, TRUE); ++ } ++#endif /* BCMSDIOH_TXGLOM */ ++ DHD_ERROR(("%s: WLAN ON DONE\n", __FUNCTION__)); + } else { + dhd_bus_stop(bus, FALSE); + dhdsdio_release_dongle(bus, bus->dhd->osh, +@@ -8123,14 +7800,18 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8 + bcmerror = BCME_SDIO_ERROR; + + #ifdef DHDTHREAD +- dhd_os_sdunlock(dhdp); ++ dhd_os_sdunlock(dhdp); + #endif /* DHDTHREAD */ + } else { + bcmerror = BCME_SDIO_ERROR; +- DHD_INFO(("%s called when dongle is not in reset\n", ++ DHD_ERROR(("%s called when dongle is not in reset\n", + __FUNCTION__)); +- DHD_INFO(("Will call dhd_bus_start instead\n")); ++ DHD_ERROR(("Will call dhd_bus_start instead\n")); + sdioh_start(NULL, 1); ++#if defined(HW_OOB) ++ bcmsdh_config_hw_oob_intr(bus->sdh, bus->sih->chip); // terence 20120615: fix for OOB initial issue ++#endif ++ COPY_FW_PATH_BY_CHIP(bus, fw_path, firmware_path); + if ((bcmerror = dhd_bus_start(dhdp)) != 0) + DHD_ERROR(("%s: dhd_bus_start fail with %d\n", + __FUNCTION__, bcmerror)); +@@ -8171,68 +7852,3 @@ dhd_bus_membytes(dhd_pub_t *dhdp, bool s + bus = dhdp->bus; + return dhdsdio_membytes(bus, set, address, data, size); + } +- +-int +-dhd_enableOOB(dhd_pub_t *dhd, bool sleep) +-{ +- dhd_bus_t *bus = dhd->bus; +- sdpcmd_regs_t *regs = bus->regs; +- uint retries = 0; +- +- if (sleep) { +- 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")); +- return BCME_BUSY; +- } +- /* Turn off our contribution to the HT clock request */ +- dhdsdio_clkctl(bus, CLK_SDONLY, FALSE); +- } else { +- /* 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); +- } +- return BCME_OK; +-} +- +-void +-dhd_bus_pktq_flush(dhd_pub_t *dhdp) +-{ +- dhd_bus_t *bus = dhdp->bus; +- /* Clear the data packet queues */ +- pktq_flush(dhdp->osh, &bus->txq, TRUE, NULL, 0); +-} +- +-int +-dhd_sr_config(dhd_pub_t *dhd, bool on) +-{ +- dhd_bus_t *bus = dhd->bus; +- +- if (!bus->_srenab) +- return -1; +- +- return dhdsdio_clk_devsleep_iovar(bus, on); +-} +- +-uint16 +-dhd_get_chipid(dhd_pub_t *dhd) +-{ +- dhd_bus_t *bus = dhd->bus; +- +- if (bus && bus->sih) +- return (uint16)bus->sih->chip; +- else +- return 0; +-} +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/dhd_wlfc.c linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_wlfc.c +--- linux-sunxi/drivers/net/wireless/bcmdhd/dhd_wlfc.c 2014-01-27 01:30:30.108433411 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_wlfc.c 1970-01-01 01:00:00.000000000 +0100 +@@ -1,2441 +0,0 @@ +-/* +- * DHD PROP_TXSTATUS Module. +- * +- * Copyright (C) 1999-2013, Broadcom Corporation +- * +- * Unless you and Broadcom execute a separate written software license +- * agreement governing use of this software, this software is licensed to you +- * under the terms of the GNU General Public License version 2 (the "GPL"), +- * available at http://www.broadcom.com/licenses/GPLv2.php, with the +- * following added to such license: +- * +- * As a special exception, the copyright holders of this software give you +- * permission to link this software with independent modules, and to copy and +- * distribute the resulting executable under terms of your choice, provided that +- * you also meet, for each linked independent module, the terms and conditions of +- * the license of that module. An independent module is a module which is not +- * derived from this software. The special exception does not apply to any +- * modifications of the software. +- * +- * Notwithstanding the above, under no circumstances may you combine this +- * software in any way with any other Broadcom software provided under a license +- * other than the GPL, without Broadcom's express prior written consent. +- * +- * $Id: dhd_wlfc.c 412994 2013-07-17 12:38:03Z $ +- * +- */ +- +-#include +-#include +- +-#include +-#include +- +-#include +-#include +- +-#include +-#include +- +-#ifdef PROP_TXSTATUS +-#include +-#include +-#endif +- +- +- +- +-#define BUS_RETRIES 1 /* # of retries before aborting a bus tx operation */ +- +-#ifdef PROP_TXSTATUS +-typedef struct dhd_wlfc_commit_info { +- uint8 needs_hdr; +- uint8 ac_fifo_credit_spent; +- ewlfc_packet_state_t pkt_type; +- wlfc_mac_descriptor_t* mac_entry; +- void* p; +-} dhd_wlfc_commit_info_t; +-#endif /* PROP_TXSTATUS */ +- +- +-#ifdef PROP_TXSTATUS +- +-#define DHD_WLFC_QMON_COMPLETE(entry) +- +-void +-dhd_wlfc_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf) +-{ +- int i; +- uint8* ea; +- athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) +- dhdp->wlfc_state; +- wlfc_hanger_t* h; +- wlfc_mac_descriptor_t* mac_table; +- wlfc_mac_descriptor_t* interfaces; +- char* iftypes[] = {"STA", "AP", "WDS", "p2pGO", "p2pCL"}; +- +- if (wlfc == NULL) { +- bcm_bprintf(strbuf, "wlfc not initialized yet\n"); +- return; +- } +- h = (wlfc_hanger_t*)wlfc->hanger; +- if (h == NULL) { +- bcm_bprintf(strbuf, "wlfc-hanger not initialized yet\n"); +- } +- +- mac_table = wlfc->destination_entries.nodes; +- interfaces = wlfc->destination_entries.interfaces; +- bcm_bprintf(strbuf, "---- wlfc stats ----\n"); +- if (h) { +- bcm_bprintf(strbuf, "wlfc hanger (pushed,popped,f_push," +- "f_pop,f_slot, pending) = (%d,%d,%d,%d,%d,%d)\n", +- h->pushed, +- h->popped, +- h->failed_to_push, +- h->failed_to_pop, +- h->failed_slotfind, +- (h->pushed - h->popped)); +- } +- +- bcm_bprintf(strbuf, "wlfc fail(tlv,credit_rqst,mac_update,psmode_update), " +- "(dq_full,rollback_fail) = (%d,%d,%d,%d), (%d,%d)\n", +- wlfc->stats.tlv_parse_failed, +- wlfc->stats.credit_request_failed, +- wlfc->stats.mac_update_failed, +- wlfc->stats.psmode_update_failed, +- wlfc->stats.delayq_full_error, +- wlfc->stats.rollback_failed); +- +- bcm_bprintf(strbuf, "PKTS (credit,sent) " +- "(AC0[%d,%d],AC1[%d,%d],AC2[%d,%d],AC3[%d,%d],BC_MC[%d,%d])\n", +- wlfc->FIFO_credit[0], wlfc->stats.send_pkts[0], +- wlfc->FIFO_credit[1], wlfc->stats.send_pkts[1], +- wlfc->FIFO_credit[2], wlfc->stats.send_pkts[2], +- wlfc->FIFO_credit[3], wlfc->stats.send_pkts[3], +- wlfc->FIFO_credit[4], wlfc->stats.send_pkts[4]); +- +- bcm_bprintf(strbuf, "\n"); +- for (i = 0; i < WLFC_MAX_IFNUM; i++) { +- if (interfaces[i].occupied) { +- char* iftype_desc; +- +- if (interfaces[i].iftype > WLC_E_IF_ROLE_P2P_CLIENT) +- iftype_desc = "hostif_flow_state[i] == OFF) +- ? " OFF":" ON")); +- +- bcm_bprintf(strbuf, "INTERFACE[%d].DELAYQ(len,state,credit)" +- "= (%d,%s,%d)\n", +- i, +- interfaces[i].psq.len, +- ((interfaces[i].state == +- WLFC_STATE_OPEN) ? " OPEN":"CLOSE"), +- interfaces[i].requested_credit); +- +- bcm_bprintf(strbuf, "INTERFACE[%d].DELAYQ" +- "(sup,ac0),(sup,ac1),(sup,ac2),(sup,ac3) = " +- "(%d,%d),(%d,%d),(%d,%d),(%d,%d)\n", +- i, +- interfaces[i].psq.q[0].len, +- interfaces[i].psq.q[1].len, +- interfaces[i].psq.q[2].len, +- interfaces[i].psq.q[3].len, +- interfaces[i].psq.q[4].len, +- interfaces[i].psq.q[5].len, +- interfaces[i].psq.q[6].len, +- interfaces[i].psq.q[7].len); +- } +- } +- +- bcm_bprintf(strbuf, "\n"); +- for (i = 0; i < WLFC_MAC_DESC_TABLE_SIZE; i++) { +- if (mac_table[i].occupied) { +- ea = mac_table[i].ea; +- bcm_bprintf(strbuf, "MAC_table[%d].ea = " +- "[%02x:%02x:%02x:%02x:%02x:%02x], if:%d \n", i, +- ea[0], ea[1], ea[2], ea[3], ea[4], ea[5], +- mac_table[i].interface_id); +- +- bcm_bprintf(strbuf, "MAC_table[%d].DELAYQ(len,state,credit)" +- "= (%d,%s,%d)\n", +- i, +- mac_table[i].psq.len, +- ((mac_table[i].state == +- WLFC_STATE_OPEN) ? " OPEN":"CLOSE"), +- mac_table[i].requested_credit); +-#ifdef PROP_TXSTATUS_DEBUG +- bcm_bprintf(strbuf, "MAC_table[%d]: (opened, closed) = (%d, %d)\n", +- i, mac_table[i].opened_ct, mac_table[i].closed_ct); +-#endif +- bcm_bprintf(strbuf, "MAC_table[%d].DELAYQ" +- "(sup,ac0),(sup,ac1),(sup,ac2),(sup,ac3) = " +- "(%d,%d),(%d,%d),(%d,%d),(%d,%d)\n", +- i, +- mac_table[i].psq.q[0].len, +- mac_table[i].psq.q[1].len, +- mac_table[i].psq.q[2].len, +- mac_table[i].psq.q[3].len, +- mac_table[i].psq.q[4].len, +- mac_table[i].psq.q[5].len, +- mac_table[i].psq.q[6].len, +- mac_table[i].psq.q[7].len); +- } +- } +- +-#ifdef PROP_TXSTATUS_DEBUG +- { +- int avg; +- int moving_avg = 0; +- int moving_samples; +- +- if (wlfc->stats.latency_sample_count) { +- moving_samples = sizeof(wlfc->stats.deltas)/sizeof(uint32); +- +- for (i = 0; i < moving_samples; i++) +- moving_avg += wlfc->stats.deltas[i]; +- moving_avg /= moving_samples; +- +- avg = (100 * wlfc->stats.total_status_latency) / +- wlfc->stats.latency_sample_count; +- bcm_bprintf(strbuf, "txstatus latency (average, last, moving[%d]) = " +- "(%d.%d, %03d, %03d)\n", +- moving_samples, avg/100, (avg - (avg/100)*100), +- wlfc->stats.latency_most_recent, +- moving_avg); +- } +- } +- +- bcm_bprintf(strbuf, "wlfc- fifo[0-5] credit stats: sent = (%d,%d,%d,%d,%d,%d), " +- "back = (%d,%d,%d,%d,%d,%d)\n", +- wlfc->stats.fifo_credits_sent[0], +- wlfc->stats.fifo_credits_sent[1], +- wlfc->stats.fifo_credits_sent[2], +- wlfc->stats.fifo_credits_sent[3], +- wlfc->stats.fifo_credits_sent[4], +- wlfc->stats.fifo_credits_sent[5], +- +- wlfc->stats.fifo_credits_back[0], +- wlfc->stats.fifo_credits_back[1], +- wlfc->stats.fifo_credits_back[2], +- wlfc->stats.fifo_credits_back[3], +- wlfc->stats.fifo_credits_back[4], +- wlfc->stats.fifo_credits_back[5]); +- { +- uint32 fifo_cr_sent = 0; +- uint32 fifo_cr_acked = 0; +- uint32 request_cr_sent = 0; +- uint32 request_cr_ack = 0; +- uint32 bc_mc_cr_ack = 0; +- +- for (i = 0; i < sizeof(wlfc->stats.fifo_credits_sent)/sizeof(uint32); i++) { +- fifo_cr_sent += wlfc->stats.fifo_credits_sent[i]; +- } +- +- for (i = 0; i < sizeof(wlfc->stats.fifo_credits_back)/sizeof(uint32); i++) { +- fifo_cr_acked += wlfc->stats.fifo_credits_back[i]; +- } +- +- for (i = 0; i < WLFC_MAC_DESC_TABLE_SIZE; i++) { +- if (wlfc->destination_entries.nodes[i].occupied) { +- request_cr_sent += +- wlfc->destination_entries.nodes[i].dstncredit_sent_packets; +- } +- } +- for (i = 0; i < WLFC_MAX_IFNUM; i++) { +- if (wlfc->destination_entries.interfaces[i].occupied) { +- request_cr_sent += +- wlfc->destination_entries.interfaces[i].dstncredit_sent_packets; +- } +- } +- for (i = 0; i < WLFC_MAC_DESC_TABLE_SIZE; i++) { +- if (wlfc->destination_entries.nodes[i].occupied) { +- request_cr_ack += +- wlfc->destination_entries.nodes[i].dstncredit_acks; +- } +- } +- for (i = 0; i < WLFC_MAX_IFNUM; i++) { +- if (wlfc->destination_entries.interfaces[i].occupied) { +- request_cr_ack += +- wlfc->destination_entries.interfaces[i].dstncredit_acks; +- } +- } +- bcm_bprintf(strbuf, "wlfc- (sent, status) => pq(%d,%d), vq(%d,%d)," +- "other:%d, bc_mc:%d, signal-only, (sent,freed): (%d,%d)", +- fifo_cr_sent, fifo_cr_acked, +- request_cr_sent, request_cr_ack, +- wlfc->destination_entries.other.dstncredit_acks, +- bc_mc_cr_ack, +- wlfc->stats.signal_only_pkts_sent, wlfc->stats.signal_only_pkts_freed); +- } +-#endif /* PROP_TXSTATUS_DEBUG */ +- bcm_bprintf(strbuf, "\n"); +- bcm_bprintf(strbuf, "wlfc- pkt((in,2bus,txstats,hdrpull),(dropped,hdr_only,wlc_tossed)" +- "(freed,free_err,rollback)) = " +- "((%d,%d,%d,%d),(%d,%d,%d),(%d,%d,%d))\n", +- wlfc->stats.pktin, +- wlfc->stats.pkt2bus, +- wlfc->stats.txstatus_in, +- wlfc->stats.dhd_hdrpulls, +- +- wlfc->stats.pktdropped, +- wlfc->stats.wlfc_header_only_pkt, +- wlfc->stats.wlc_tossed_pkts, +- +- wlfc->stats.pkt_freed, +- wlfc->stats.pkt_free_err, wlfc->stats.rollback); +- +- bcm_bprintf(strbuf, "wlfc- suppress((d11,wlc,err),enq(d11,wl,hq,mac?),retx(d11,wlc,hq)) = " +- "((%d,%d,%d),(%d,%d,%d,%d),(%d,%d,%d))\n", +- +- wlfc->stats.d11_suppress, +- wlfc->stats.wl_suppress, +- wlfc->stats.bad_suppress, +- +- wlfc->stats.psq_d11sup_enq, +- wlfc->stats.psq_wlsup_enq, +- wlfc->stats.psq_hostq_enq, +- wlfc->stats.mac_handle_notfound, +- +- wlfc->stats.psq_d11sup_retx, +- wlfc->stats.psq_wlsup_retx, +- wlfc->stats.psq_hostq_retx); +- bcm_bprintf(strbuf, "wlfc- generic error: %d", wlfc->stats.generic_error); +- +- return; +-} +- +-/* Create a place to store all packet pointers submitted to the firmware until +- a status comes back, suppress or otherwise. +- +- hang-er: noun, a contrivance on which things are hung, as a hook. +-*/ +-static void* +-dhd_wlfc_hanger_create(osl_t *osh, int max_items) +-{ +- int i; +- wlfc_hanger_t* hanger; +- +- /* allow only up to a specific size for now */ +- ASSERT(max_items == WLFC_HANGER_MAXITEMS); +- +- if ((hanger = (wlfc_hanger_t*)MALLOC(osh, WLFC_HANGER_SIZE(max_items))) == NULL) +- return NULL; +- +- memset(hanger, 0, WLFC_HANGER_SIZE(max_items)); +- hanger->max_items = max_items; +- +- for (i = 0; i < hanger->max_items; i++) { +- hanger->items[i].state = WLFC_HANGER_ITEM_STATE_FREE; +- } +- return hanger; +-} +- +-static int +-dhd_wlfc_hanger_delete(osl_t *osh, void* hanger) +-{ +- wlfc_hanger_t* h = (wlfc_hanger_t*)hanger; +- +- if (h) { +- MFREE(osh, h, WLFC_HANGER_SIZE(h->max_items)); +- return BCME_OK; +- } +- return BCME_BADARG; +-} +- +-static uint16 +-dhd_wlfc_hanger_get_free_slot(void* hanger) +-{ +- uint32 i; +- wlfc_hanger_t* h = (wlfc_hanger_t*)hanger; +- +- if (h) { +- i = h->slot_pos + 1; +- if (i == h->max_items) { +- i = 0; +- } +- while (i != h->slot_pos) { +- if (h->items[i].state == WLFC_HANGER_ITEM_STATE_FREE) { +- h->slot_pos = i; +- return (uint16)i; +- } +- i++; +- if (i == h->max_items) +- i = 0; +- } +- h->failed_slotfind++; +- } +- return WLFC_HANGER_MAXITEMS; +-} +- +-static int +-dhd_wlfc_hanger_get_genbit(void* hanger, void* pkt, uint32 slot_id, int* gen) +-{ +- int rc = BCME_OK; +- wlfc_hanger_t* h = (wlfc_hanger_t*)hanger; +- +- *gen = 0xff; +- +- /* this packet was not pushed at the time it went to the firmware */ +- if (slot_id == WLFC_HANGER_MAXITEMS) +- return BCME_NOTFOUND; +- +- if (h) { +- if ((h->items[slot_id].state == WLFC_HANGER_ITEM_STATE_INUSE) || +- (h->items[slot_id].state == WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED)) { +- *gen = h->items[slot_id].gen; +- } +- else { +- rc = BCME_NOTFOUND; +- } +- } +- else +- rc = BCME_BADARG; +- return rc; +-} +- +-static int +-dhd_wlfc_hanger_pushpkt(void* hanger, void* pkt, uint32 slot_id) +-{ +- int rc = BCME_OK; +- wlfc_hanger_t* h = (wlfc_hanger_t*)hanger; +- +- if (h && (slot_id < WLFC_HANGER_MAXITEMS)) { +- if (h->items[slot_id].state == WLFC_HANGER_ITEM_STATE_FREE) { +- h->items[slot_id].state = WLFC_HANGER_ITEM_STATE_INUSE; +- h->items[slot_id].pkt = pkt; +- h->items[slot_id].identifier = slot_id; +- h->pushed++; +- } +- else { +- h->failed_to_push++; +- rc = BCME_NOTFOUND; +- } +- } +- else +- rc = BCME_BADARG; +- return rc; +-} +- +-static int +-dhd_wlfc_hanger_poppkt(void* hanger, uint32 slot_id, void** pktout, int remove_from_hanger) +-{ +- int rc = BCME_OK; +- wlfc_hanger_t* h = (wlfc_hanger_t*)hanger; +- +- /* this packet was not pushed at the time it went to the firmware */ +- if (slot_id == WLFC_HANGER_MAXITEMS) +- return BCME_NOTFOUND; +- +- if (h) { +- if (h->items[slot_id].state != WLFC_HANGER_ITEM_STATE_FREE) { +- *pktout = h->items[slot_id].pkt; +- if (remove_from_hanger) { +- h->items[slot_id].state = +- WLFC_HANGER_ITEM_STATE_FREE; +- h->items[slot_id].pkt = NULL; +- h->items[slot_id].identifier = 0; +- h->items[slot_id].gen = 0xff; +- h->popped++; +- } +- } +- else { +- h->failed_to_pop++; +- rc = BCME_NOTFOUND; +- } +- } +- else +- rc = BCME_BADARG; +- return rc; +-} +- +-static int +-dhd_wlfc_hanger_mark_suppressed(void* hanger, uint32 slot_id, uint8 gen) +-{ +- int rc = BCME_OK; +- wlfc_hanger_t* h = (wlfc_hanger_t*)hanger; +- +- /* this packet was not pushed at the time it went to the firmware */ +- if (slot_id == WLFC_HANGER_MAXITEMS) +- return BCME_NOTFOUND; +- if (h) { +- h->items[slot_id].gen = gen; +- if (h->items[slot_id].state == WLFC_HANGER_ITEM_STATE_INUSE) { +- h->items[slot_id].state = WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED; +- } +- else +- rc = BCME_BADARG; +- } +- else +- rc = BCME_BADARG; +- +- return rc; +-} +- +-static int +-_dhd_wlfc_pushheader(athost_wl_status_info_t* ctx, void* p, bool tim_signal, +- uint8 tim_bmp, uint8 mac_handle, uint32 htodtag) +-{ +- uint32 wl_pktinfo = 0; +- uint8* wlh; +- uint8 dataOffset; +- uint8 fillers; +- uint8 tim_signal_len = 0; +- +- struct bdc_header *h; +- +- if (tim_signal) { +- tim_signal_len = 1 + 1 + WLFC_CTL_VALUE_LEN_PENDING_TRAFFIC_BMP; +- } +- +- /* +2 is for Type[1] and Len[1] in TLV, plus TIM signal */ +- dataOffset = WLFC_CTL_VALUE_LEN_PKTTAG + 2 + tim_signal_len; +- fillers = ROUNDUP(dataOffset, 4) - dataOffset; +- dataOffset += fillers; +- +- PKTPUSH(ctx->osh, p, dataOffset); +- wlh = (uint8*) PKTDATA(ctx->osh, p); +- +- wl_pktinfo = htol32(htodtag); +- +- wlh[0] = WLFC_CTL_TYPE_PKTTAG; +- wlh[1] = WLFC_CTL_VALUE_LEN_PKTTAG; +- memcpy(&wlh[2], &wl_pktinfo, sizeof(uint32)); +- +- if (tim_signal_len) { +- wlh[dataOffset - fillers - tim_signal_len ] = +- WLFC_CTL_TYPE_PENDING_TRAFFIC_BMP; +- wlh[dataOffset - fillers - tim_signal_len + 1] = +- WLFC_CTL_VALUE_LEN_PENDING_TRAFFIC_BMP; +- wlh[dataOffset - fillers - tim_signal_len + 2] = mac_handle; +- wlh[dataOffset - fillers - tim_signal_len + 3] = tim_bmp; +- } +- if (fillers) +- memset(&wlh[dataOffset - fillers], WLFC_CTL_TYPE_FILLER, fillers); +- +- PKTPUSH(ctx->osh, p, BDC_HEADER_LEN); +- h = (struct bdc_header *)PKTDATA(ctx->osh, p); +- h->flags = (BDC_PROTO_VER << BDC_FLAG_VER_SHIFT); +- if (PKTSUMNEEDED(p)) +- h->flags |= BDC_FLAG_SUM_NEEDED; +- +- +- h->priority = (PKTPRIO(p) & BDC_PRIORITY_MASK); +- h->flags2 = 0; +- h->dataOffset = dataOffset >> 2; +- BDC_SET_IF_IDX(h, DHD_PKTTAG_IF(PKTTAG(p))); +- return BCME_OK; +-} +- +-static int +-_dhd_wlfc_pullheader(athost_wl_status_info_t* ctx, void* pktbuf) +-{ +- struct bdc_header *h; +- +- if (PKTLEN(ctx->osh, pktbuf) < BDC_HEADER_LEN) { +- WLFC_DBGMESG(("%s: rx data too short (%d < %d)\n", __FUNCTION__, +- PKTLEN(ctx->osh, pktbuf), BDC_HEADER_LEN)); +- return BCME_ERROR; +- } +- h = (struct bdc_header *)PKTDATA(ctx->osh, pktbuf); +- +- /* pull BDC header */ +- PKTPULL(ctx->osh, pktbuf, BDC_HEADER_LEN); +- +- if (PKTLEN(ctx->osh, pktbuf) < (h->dataOffset << 2)) { +- WLFC_DBGMESG(("%s: rx data too short (%d < %d)\n", __FUNCTION__, +- PKTLEN(ctx->osh, pktbuf), (h->dataOffset << 2))); +- return BCME_ERROR; +- } +- +- /* pull wl-header */ +- PKTPULL(ctx->osh, pktbuf, (h->dataOffset << 2)); +- return BCME_OK; +-} +- +-static wlfc_mac_descriptor_t* +-_dhd_wlfc_find_table_entry(athost_wl_status_info_t* ctx, void* p) +-{ +- int i; +- wlfc_mac_descriptor_t* table = ctx->destination_entries.nodes; +- uint8 ifid = DHD_PKTTAG_IF(PKTTAG(p)); +- uint8* dstn = DHD_PKTTAG_DSTN(PKTTAG(p)); +- wlfc_mac_descriptor_t* entry = NULL; +- int iftype = ctx->destination_entries.interfaces[ifid].iftype; +- +- /* Multicast destination and P2P clients get the interface entry. +- * STA gets the interface entry if there is no exact match. For +- * example, TDLS destinations have their own entry. +- */ +- if ((iftype == WLC_E_IF_ROLE_STA || ETHER_ISMULTI(dstn) || +- iftype == WLC_E_IF_ROLE_P2P_CLIENT) && +- (ctx->destination_entries.interfaces[ifid].occupied)) { +- entry = &ctx->destination_entries.interfaces[ifid]; +- } +- +- if (entry != NULL && ETHER_ISMULTI(dstn)) +- return entry; +- +- for (i = 0; i < WLFC_MAC_DESC_TABLE_SIZE; i++) { +- if (table[i].occupied) { +- if (table[i].interface_id == ifid) { +- if (!memcmp(table[i].ea, dstn, ETHER_ADDR_LEN)) { +- entry = &table[i]; +- break; +- } +- } +- } +- } +- +- return entry != NULL ? entry : &ctx->destination_entries.other; +-} +- +-static int +-_dhd_wlfc_rollback_packet_toq(athost_wl_status_info_t* ctx, +- void* p, ewlfc_packet_state_t pkt_type, uint32 hslot) +-{ +- /* +- put the packet back to the head of queue +- +- - suppressed packet goes back to suppress sub-queue +- - pull out the header, if new or delayed packet +- +- Note: hslot is used only when header removal is done. +- */ +- wlfc_mac_descriptor_t* entry; +- void* pktout; +- int rc = BCME_OK; +- int prec; +- +- entry = _dhd_wlfc_find_table_entry(ctx, p); +- prec = DHD_PKTTAG_FIFO(PKTTAG(p)); +- if (entry != NULL) { +- if (pkt_type == eWLFC_PKTTYPE_SUPPRESSED) { +- /* wl-header is saved for suppressed packets */ +- if (WLFC_PKTQ_PENQ_HEAD(&entry->psq, ((prec << 1) + 1), p) == NULL) { +- WLFC_DBGMESG(("Error: %s():%d\n", __FUNCTION__, __LINE__)); +- rc = BCME_ERROR; +- } +- } +- else { +- /* remove header first */ +- rc = _dhd_wlfc_pullheader(ctx, p); +- if (rc != BCME_OK) { +- WLFC_DBGMESG(("Error: %s():%d\n", __FUNCTION__, __LINE__)); +- /* free the hanger slot */ +- dhd_wlfc_hanger_poppkt(ctx->hanger, hslot, &pktout, 1); +- PKTFREE(ctx->osh, p, TRUE); +- ctx->stats.rollback_failed++; +- return BCME_ERROR; +- } +- +- if (pkt_type == eWLFC_PKTTYPE_DELAYED) { +- /* delay-q packets are going to delay-q */ +- if (WLFC_PKTQ_PENQ_HEAD(&entry->psq, (prec << 1), p) == NULL) { +- WLFC_DBGMESG(("Error: %s():%d\n", __FUNCTION__, __LINE__)); +- rc = BCME_ERROR; +- } +- } +- +- /* free the hanger slot */ +- dhd_wlfc_hanger_poppkt(ctx->hanger, hslot, &pktout, 1); +- +- /* decrement sequence count */ +- WLFC_DECR_SEQCOUNT(entry, prec); +- } +- /* +- if this packet did not count against FIFO credit, it must have +- taken a requested_credit from the firmware (for pspoll etc.) +- */ +- if (!DHD_PKTTAG_CREDITCHECK(PKTTAG(p))) { +- entry->requested_credit++; +- } +- } +- else { +- WLFC_DBGMESG(("Error: %s():%d\n", __FUNCTION__, __LINE__)); +- rc = BCME_ERROR; +- } +- if (rc != BCME_OK) +- ctx->stats.rollback_failed++; +- else +- ctx->stats.rollback++; +- +- return rc; +-} +- +-static void +-_dhd_wlfc_flow_control_check(athost_wl_status_info_t* ctx, struct pktq* pq, uint8 if_id) +-{ +- dhd_pub_t *dhdp; +- +- ASSERT(ctx); +- +- dhdp = (dhd_pub_t *)ctx->dhdp; +- +- if (dhdp && dhdp->skip_fc && dhdp->skip_fc()) +- return; +- +- if ((pq->len <= WLFC_FLOWCONTROL_LOWATER) && (ctx->hostif_flow_state[if_id] == ON)) { +- /* start traffic */ +- ctx->hostif_flow_state[if_id] = OFF; +- /* +- WLFC_DBGMESG(("qlen:%02d, if:%02d, ->OFF, start traffic %s()\n", +- pq->len, if_id, __FUNCTION__)); +- */ +- WLFC_DBGMESG(("F")); +- +- dhd_txflowcontrol(ctx->dhdp, if_id, OFF); +- +- ctx->toggle_host_if = 0; +- } +- if ((pq->len >= WLFC_FLOWCONTROL_HIWATER) && (ctx->hostif_flow_state[if_id] == OFF)) { +- /* stop traffic */ +- ctx->hostif_flow_state[if_id] = ON; +- /* +- WLFC_DBGMESG(("qlen:%02d, if:%02d, ->ON, stop traffic %s()\n", +- pq->len, if_id, __FUNCTION__)); +- */ +- WLFC_DBGMESG(("N")); +- +- dhd_txflowcontrol(ctx->dhdp, if_id, ON); +- +- ctx->host_ifidx = if_id; +- ctx->toggle_host_if = 1; +- } +- +- return; +-} +- +-static int +-_dhd_wlfc_send_signalonly_packet(athost_wl_status_info_t* ctx, wlfc_mac_descriptor_t* entry, +- uint8 ta_bmp) +-{ +- int rc = BCME_OK; +- void* p = NULL; +- int dummylen = ((dhd_pub_t *)ctx->dhdp)->hdrlen+ 12; +- +- /* allocate a dummy packet */ +- p = PKTGET(ctx->osh, dummylen, TRUE); +- if (p) { +- PKTPULL(ctx->osh, p, dummylen); +- DHD_PKTTAG_SET_H2DTAG(PKTTAG(p), 0); +- _dhd_wlfc_pushheader(ctx, p, TRUE, ta_bmp, entry->mac_handle, 0); +- DHD_PKTTAG_SETSIGNALONLY(PKTTAG(p), 1); +-#ifdef PROP_TXSTATUS_DEBUG +- ctx->stats.signal_only_pkts_sent++; +-#endif +- rc = dhd_bus_txdata(((dhd_pub_t *)ctx->dhdp)->bus, p); +- if (rc != BCME_OK) { +- PKTFREE(ctx->osh, p, TRUE); +- } +- } +- else { +- DHD_ERROR(("%s: couldn't allocate new %d-byte packet\n", +- __FUNCTION__, dummylen)); +- rc = BCME_NOMEM; +- } +- return rc; +-} +- +-/* Return TRUE if traffic availability changed */ +-static bool +-_dhd_wlfc_traffic_pending_check(athost_wl_status_info_t* ctx, wlfc_mac_descriptor_t* entry, +- int prec) +-{ +- bool rc = FALSE; +- +- if (entry->state == WLFC_STATE_CLOSE) { +- if ((pktq_plen(&entry->psq, (prec << 1)) == 0) && +- (pktq_plen(&entry->psq, ((prec << 1) + 1)) == 0)) { +- +- if (entry->traffic_pending_bmp & NBITVAL(prec)) { +- rc = TRUE; +- entry->traffic_pending_bmp = +- entry->traffic_pending_bmp & ~ NBITVAL(prec); +- } +- } +- else { +- if (!(entry->traffic_pending_bmp & NBITVAL(prec))) { +- rc = TRUE; +- entry->traffic_pending_bmp = +- entry->traffic_pending_bmp | NBITVAL(prec); +- } +- } +- } +- if (rc) { +- /* request a TIM update to firmware at the next piggyback opportunity */ +- if (entry->traffic_lastreported_bmp != entry->traffic_pending_bmp) { +- entry->send_tim_signal = 1; +- _dhd_wlfc_send_signalonly_packet(ctx, entry, entry->traffic_pending_bmp); +- entry->traffic_lastreported_bmp = entry->traffic_pending_bmp; +- entry->send_tim_signal = 0; +- } +- else { +- rc = FALSE; +- } +- } +- return rc; +-} +- +-static int +-_dhd_wlfc_enque_suppressed(athost_wl_status_info_t* ctx, int prec, void* p) +-{ +- wlfc_mac_descriptor_t* entry; +- +- entry = _dhd_wlfc_find_table_entry(ctx, p); +- if (entry == NULL) { +- WLFC_DBGMESG(("Error: %s():%d\n", __FUNCTION__, __LINE__)); +- return BCME_NOTFOUND; +- } +- /* +- - suppressed packets go to sub_queue[2*prec + 1] AND +- - delayed packets go to sub_queue[2*prec + 0] to ensure +- order of delivery. +- */ +- if (WLFC_PKTQ_PENQ(&entry->psq, ((prec << 1) + 1), p) == NULL) { +- ctx->stats.delayq_full_error++; +- /* WLFC_DBGMESG(("Error: %s():%d\n", __FUNCTION__, __LINE__)); */ +- WLFC_DBGMESG(("s")); +- return BCME_ERROR; +- } +- /* A packet has been pushed, update traffic availability bitmap, if applicable */ +- _dhd_wlfc_traffic_pending_check(ctx, entry, prec); +- _dhd_wlfc_flow_control_check(ctx, &entry->psq, DHD_PKTTAG_IF(PKTTAG(p))); +- return BCME_OK; +-} +- +-static int +-_dhd_wlfc_pretx_pktprocess(athost_wl_status_info_t* ctx, +- wlfc_mac_descriptor_t* entry, void* p, int header_needed, uint32* slot) +-{ +- int rc = BCME_OK; +- int hslot = WLFC_HANGER_MAXITEMS; +- bool send_tim_update = FALSE; +- uint32 htod = 0; +- uint8 free_ctr; +- +- *slot = hslot; +- +- if (entry == NULL) { +- entry = _dhd_wlfc_find_table_entry(ctx, p); +- } +- +- if (entry == NULL) { +- WLFC_DBGMESG(("Error: %s():%d\n", __FUNCTION__, __LINE__)); +- return BCME_ERROR; +- } +- if (entry->send_tim_signal) { +- send_tim_update = TRUE; +- entry->send_tim_signal = 0; +- entry->traffic_lastreported_bmp = entry->traffic_pending_bmp; +- } +- if (header_needed) { +- hslot = dhd_wlfc_hanger_get_free_slot(ctx->hanger); +- free_ctr = WLFC_SEQCOUNT(entry, DHD_PKTTAG_FIFO(PKTTAG(p))); +- DHD_PKTTAG_SET_H2DTAG(PKTTAG(p), htod); +- WLFC_PKTFLAG_SET_GENERATION(htod, entry->generation); +- entry->transit_count++; +- } +- else { +- hslot = WLFC_PKTID_HSLOT_GET(DHD_PKTTAG_H2DTAG(PKTTAG(p))); +- free_ctr = WLFC_PKTID_FREERUNCTR_GET(DHD_PKTTAG_H2DTAG(PKTTAG(p))); +- } +- WLFC_PKTID_HSLOT_SET(htod, hslot); +- WLFC_PKTID_FREERUNCTR_SET(htod, free_ctr); +- DHD_PKTTAG_SETPKTDIR(PKTTAG(p), 1); +- WL_TXSTATUS_SET_FLAGS(htod, WLFC_PKTFLAG_PKTFROMHOST); +- WL_TXSTATUS_SET_FIFO(htod, DHD_PKTTAG_FIFO(PKTTAG(p))); +- +- +- if (!DHD_PKTTAG_CREDITCHECK(PKTTAG(p))) { +- /* +- Indicate that this packet is being sent in response to an +- explicit request from the firmware side. +- */ +- WLFC_PKTFLAG_SET_PKTREQUESTED(htod); +- } +- else { +- WLFC_PKTFLAG_CLR_PKTREQUESTED(htod); +- } +- if (header_needed) { +- rc = _dhd_wlfc_pushheader(ctx, p, send_tim_update, +- entry->traffic_lastreported_bmp, entry->mac_handle, htod); +- if (rc == BCME_OK) { +- DHD_PKTTAG_SET_H2DTAG(PKTTAG(p), htod); +- /* +- a new header was created for this packet. +- push to hanger slot and scrub q. Since bus +- send succeeded, increment seq number as well. +- */ +- rc = dhd_wlfc_hanger_pushpkt(ctx->hanger, p, hslot); +- if (rc == BCME_OK) { +- /* increment free running sequence count */ +- WLFC_INCR_SEQCOUNT(entry, DHD_PKTTAG_FIFO(PKTTAG(p))); +-#ifdef PROP_TXSTATUS_DEBUG +- ((wlfc_hanger_t*)(ctx->hanger))->items[hslot].push_time = +- OSL_SYSUPTIME(); +-#endif +- } +- else { +- WLFC_DBGMESG(("%s() hanger_pushpkt() failed, rc: %d\n", +- __FUNCTION__, rc)); +- } +- } +- } +- else { +- int gen; +- +- /* remove old header */ +- rc = _dhd_wlfc_pullheader(ctx, p); +- if (rc == BCME_OK) { +- hslot = WLFC_PKTID_HSLOT_GET(DHD_PKTTAG_H2DTAG(PKTTAG(p))); +- dhd_wlfc_hanger_get_genbit(ctx->hanger, p, hslot, &gen); +- +- WLFC_PKTFLAG_SET_GENERATION(htod, gen); +- free_ctr = WLFC_PKTID_FREERUNCTR_GET(DHD_PKTTAG_H2DTAG(PKTTAG(p))); +- /* push new header */ +- _dhd_wlfc_pushheader(ctx, p, send_tim_update, +- entry->traffic_lastreported_bmp, entry->mac_handle, htod); +- } +- } +- *slot = hslot; +- return rc; +-} +- +-static int +-_dhd_wlfc_is_destination_closed(athost_wl_status_info_t* ctx, +- wlfc_mac_descriptor_t* entry, int prec) +-{ +- if (ctx->destination_entries.interfaces[entry->interface_id].iftype == +- WLC_E_IF_ROLE_P2P_GO) { +- /* - destination interface is of type p2p GO. +- For a p2pGO interface, if the destination is OPEN but the interface is +- CLOSEd, do not send traffic. But if the dstn is CLOSEd while there is +- destination-specific-credit left send packets. This is because the +- firmware storing the destination-specific-requested packet in queue. +- */ +- if ((entry->state == WLFC_STATE_CLOSE) && (entry->requested_credit == 0) && +- (entry->requested_packet == 0)) +- return 1; +- } +- /* AP, p2p_go -> unicast desc entry, STA/p2p_cl -> interface desc. entry */ +- if (((entry->state == WLFC_STATE_CLOSE) && (entry->requested_credit == 0) && +- (entry->requested_packet == 0)) || +- (!(entry->ac_bitmap & (1 << prec)))) +- return 1; +- +- return 0; +-} +- +-static void* +-_dhd_wlfc_deque_delayedq(athost_wl_status_info_t* ctx, +- int prec, uint8* ac_credit_spent, uint8* needs_hdr, wlfc_mac_descriptor_t** entry_out) +-{ +- wlfc_mac_descriptor_t* entry; +- wlfc_mac_descriptor_t* table; +- uint8 token_pos; +- int total_entries; +- void* p = NULL; +- int pout; +- int i; +- +- *entry_out = NULL; +- token_pos = ctx->token_pos[prec]; +- /* most cases a packet will count against FIFO credit */ +- *ac_credit_spent = 1; +- *needs_hdr = 1; +- +- /* search all entries, include nodes as well as interfaces */ +- table = (wlfc_mac_descriptor_t*)&ctx->destination_entries; +- total_entries = sizeof(ctx->destination_entries)/sizeof(wlfc_mac_descriptor_t); +- +- for (i = 0; i < total_entries; i++) { +- entry = &table[(token_pos + i) % total_entries]; +- if (entry->occupied && !entry->deleting) { +- if (!_dhd_wlfc_is_destination_closed(ctx, entry, prec)) { +- p = pktq_mdeq(&entry->psq, +- /* higher precedence will be picked up first, +- * i.e. suppressed packets before delayed ones +- */ +- NBITVAL((prec << 1) + 1), &pout); +- *needs_hdr = 0; +- +- if (p == NULL) { +- if (entry->suppressed == TRUE) { +- if ((entry->suppr_transit_count <= +- entry->suppress_count)) { +- entry->suppressed = FALSE; +- } else { +- return NULL; +- } +- } +- /* De-Q from delay Q */ +- p = pktq_mdeq(&entry->psq, +- NBITVAL((prec << 1)), +- &pout); +- *needs_hdr = 1; +- } +- +- if (p != NULL) { +- /* did the packet come from suppress sub-queue? */ +- if (entry->requested_credit > 0) { +- entry->requested_credit--; +-#ifdef PROP_TXSTATUS_DEBUG +- entry->dstncredit_sent_packets++; +-#endif +- /* +- if the packet was pulled out while destination is in +- closed state but had a non-zero packets requested, +- then this should not count against the FIFO credit. +- That is due to the fact that the firmware will +- most likely hold onto this packet until a suitable +- time later to push it to the appropriate AC FIFO. +- */ +- if (entry->state == WLFC_STATE_CLOSE) +- *ac_credit_spent = 0; +- } +- else if (entry->requested_packet > 0) { +- entry->requested_packet--; +- DHD_PKTTAG_SETONETIMEPKTRQST(PKTTAG(p)); +- if (entry->state == WLFC_STATE_CLOSE) +- *ac_credit_spent = 0; +- } +- /* move token to ensure fair round-robin */ +- ctx->token_pos[prec] = +- (token_pos + i + 1) % total_entries; +- *entry_out = entry; +- _dhd_wlfc_flow_control_check(ctx, &entry->psq, +- DHD_PKTTAG_IF(PKTTAG(p))); +- /* +- A packet has been picked up, update traffic +- availability bitmap, if applicable +- */ +- _dhd_wlfc_traffic_pending_check(ctx, entry, prec); +- return p; +- } +- } +- } +- } +- return NULL; +-} +- +-void * +-_dhd_wlfc_pktq_peek_tail(struct pktq *pq, int *prec_out) +-{ +- int prec; +- +- ASSERT(pq); +- +- if (pq->len == 0) +- return NULL; +- +- for (prec = 0; prec < pq->hi_prec; prec++) +- /* only pick packets from dealyed-q */ +- if (((prec & 1) == 0) && pq->q[prec].head) +- break; +- +- if (prec_out) +- *prec_out = prec; +- +- return (pq->q[prec].tail); +-} +- +-bool +-_dhd_wlfc_prec_enq_with_drop(dhd_pub_t *dhdp, struct pktq *pq, void *pkt, int prec) +-{ +- void *p = NULL; +- int eprec = -1; /* precedence to evict from */ +- +- ASSERT(dhdp && pq && pkt); +- ASSERT(prec >= 0 && prec < pq->num_prec); +- +- /* Fast case, precedence queue is not full and we are also not +- * exceeding total queue length +- */ +- if (!pktq_pfull(pq, prec) && !pktq_full(pq)) { +- pktq_penq(pq, prec, pkt); +- return TRUE; +- } +- +- /* Determine precedence from which to evict packet, if any */ +- if (pktq_pfull(pq, prec)) +- eprec = prec; +- else if (pktq_full(pq)) { +- p = _dhd_wlfc_pktq_peek_tail(pq, &eprec); +- if (!p) { +- WLFC_DBGMESG(("Error: %s():%d\n", __FUNCTION__, __LINE__)); +- return FALSE; +- } +- if ((eprec > prec) || (eprec < 0)) { +- if (!pktq_pempty(pq, prec)) { +- eprec = prec; +- } else { +- return FALSE; +- } +- } +- } +- +- /* Evict if needed */ +- if (eprec >= 0) { +- /* Detect queueing to unconfigured precedence */ +- ASSERT(!pktq_pempty(pq, eprec)); +- /* Evict all fragmented frames */ +- dhd_prec_drop_pkts(dhdp->osh, pq, eprec); +- } +- +- /* Enqueue */ +- p = pktq_penq(pq, prec, pkt); +- if (!p) { +- WLFC_DBGMESG(("Error: %s():%d\n", __FUNCTION__, __LINE__)); +- return FALSE; +- } +- +- return TRUE; +-} +- +-static int +-_dhd_wlfc_enque_delayq(athost_wl_status_info_t* ctx, void* pktbuf, int prec) +-{ +- wlfc_mac_descriptor_t* entry; +- +- if (pktbuf != NULL) { +- entry = _dhd_wlfc_find_table_entry(ctx, pktbuf); +- +- if (entry == NULL) { +- WLFC_DBGMESG(("Error: %s():%d\n", __FUNCTION__, __LINE__)); +- return BCME_ERROR; +- } +- +- /* +- - suppressed packets go to sub_queue[2*prec + 1] AND +- - delayed packets go to sub_queue[2*prec + 0] to ensure +- order of delivery. +- */ +- if (_dhd_wlfc_prec_enq_with_drop(ctx->dhdp, &entry->psq, pktbuf, (prec << 1)) +- == FALSE) { +- WLFC_DBGMESG(("D")); +- /* dhd_txcomplete(ctx->dhdp, pktbuf, FALSE); */ +- PKTFREE(ctx->osh, pktbuf, TRUE); +- ctx->stats.delayq_full_error++; +- return BCME_ERROR; +- } +- +- /* +- A packet has been pushed, update traffic availability bitmap, +- if applicable +- */ +- _dhd_wlfc_traffic_pending_check(ctx, entry, prec); +- +- } +- return BCME_OK; +-} +- +-bool ifpkt_fn(void* p, int ifid) +-{ +- return (ifid == DHD_PKTTAG_IF(PKTTAG(p))); +-} +- +-static int +-_dhd_wlfc_mac_entry_update(athost_wl_status_info_t* ctx, wlfc_mac_descriptor_t* entry, +- ewlfc_mac_entry_action_t action, uint8 ifid, uint8 iftype, uint8* ea) +-{ +- int rc = BCME_OK; +- +- if (action == eWLFC_MAC_ENTRY_ACTION_ADD) { +- entry->occupied = 1; +- entry->state = WLFC_STATE_OPEN; +- entry->requested_credit = 0; +- entry->interface_id = ifid; +- entry->iftype = iftype; +- entry->ac_bitmap = 0xff; /* update this when handling APSD */ +- /* for an interface entry we may not care about the MAC address */ +- if (ea != NULL) +- memcpy(&entry->ea[0], ea, ETHER_ADDR_LEN); +- pktq_init(&entry->psq, WLFC_PSQ_PREC_COUNT, WLFC_PSQ_LEN); +- } +- else if (action == eWLFC_MAC_ENTRY_ACTION_UPDATE) { +- entry->occupied = 1; +- entry->state = WLFC_STATE_OPEN; +- entry->requested_credit = 0; +- entry->interface_id = ifid; +- entry->iftype = iftype; +- entry->ac_bitmap = 0xff; /* update this when handling APSD */ +- /* for an interface entry we may not care about the MAC address */ +- if (ea != NULL) +- memcpy(&entry->ea[0], ea, ETHER_ADDR_LEN); +- } +- else if (action == eWLFC_MAC_ENTRY_ACTION_DEL) { +- /* When the entry is deleted, the packets that are queued in the entry must be +- cleanup. The cleanup action should be before the occupied is set as 0. The +- flag deleting is set to avoid de-queue action when these queues are being +- cleanup +- */ +- entry->deleting = 1; +- dhd_wlfc_cleanup(ctx->dhdp, ifpkt_fn, ifid); +- _dhd_wlfc_flow_control_check(ctx, &entry->psq, ifid); +- entry->deleting = 0; +- +- entry->occupied = 0; +- entry->suppressed = 0; +- entry->state = WLFC_STATE_CLOSE; +- entry->requested_credit = 0; +- entry->transit_count = 0; +- entry->suppr_transit_count = 0; +- entry->suppress_count = 0; +- memset(&entry->ea[0], 0, ETHER_ADDR_LEN); +- +- /* enable after packets are queued-deqeued properly. +- pktq_flush(dhd->osh, &entry->psq, FALSE, NULL, 0); +- */ +- } +- return rc; +-} +- +-int +-_dhd_wlfc_borrow_credit(athost_wl_status_info_t* ctx, uint8 available_credit_map, int borrower_ac) +-{ +- int lender_ac; +- int rc = BCME_ERROR; +- +- if (ctx == NULL || available_credit_map == 0) { +- WLFC_DBGMESG(("Error: %s():%d\n", __FUNCTION__, __LINE__)); +- return BCME_BADARG; +- } +- +- /* Borrow from lowest priority available AC (including BC/MC credits) */ +- for (lender_ac = 0; lender_ac <= AC_COUNT; lender_ac++) { +- if ((available_credit_map && (1 << lender_ac)) && +- (ctx->FIFO_credit[lender_ac] > 0)) { +- ctx->credits_borrowed[borrower_ac][lender_ac]++; +- ctx->FIFO_credit[lender_ac]--; +- rc = BCME_OK; +- break; +- } +- } +- +- return rc; +-} +- +-int +-dhd_wlfc_interface_entry_update(void* state, +- ewlfc_mac_entry_action_t action, uint8 ifid, uint8 iftype, uint8* ea) +-{ +- athost_wl_status_info_t* ctx = (athost_wl_status_info_t*)state; +- wlfc_mac_descriptor_t* entry; +- int ret; +- +- if (ifid >= WLFC_MAX_IFNUM) +- return BCME_BADARG; +- +- entry = &ctx->destination_entries.interfaces[ifid]; +- ret = _dhd_wlfc_mac_entry_update(ctx, entry, action, ifid, iftype, ea); +- return ret; +-} +- +-int +-dhd_wlfc_FIFOcreditmap_update(void* state, uint8* credits) +-{ +- athost_wl_status_info_t* ctx = (athost_wl_status_info_t*)state; +- +- /* update the AC FIFO credit map */ +- ctx->FIFO_credit[0] = credits[0]; +- ctx->FIFO_credit[1] = credits[1]; +- ctx->FIFO_credit[2] = credits[2]; +- ctx->FIFO_credit[3] = credits[3]; +- /* credit for bc/mc packets */ +- ctx->FIFO_credit[4] = credits[4]; +- /* credit for ATIM FIFO is not used yet. */ +- ctx->FIFO_credit[5] = 0; +- return BCME_OK; +-} +- +-int +-_dhd_wlfc_handle_packet_commit(athost_wl_status_info_t* ctx, int ac, +- dhd_wlfc_commit_info_t *commit_info, f_commitpkt_t fcommit, void* commit_ctx) +-{ +- uint32 hslot; +- int rc; +- +- /* +- if ac_fifo_credit_spent = 0 +- +- This packet will not count against the FIFO credit. +- To ensure the txstatus corresponding to this packet +- does not provide an implied credit (default behavior) +- mark the packet accordingly. +- +- if ac_fifo_credit_spent = 1 +- +- This is a normal packet and it counts against the FIFO +- credit count. +- */ +- DHD_PKTTAG_SETCREDITCHECK(PKTTAG(commit_info->p), commit_info->ac_fifo_credit_spent); +- rc = _dhd_wlfc_pretx_pktprocess(ctx, commit_info->mac_entry, commit_info->p, +- commit_info->needs_hdr, &hslot); +- +- if (rc == BCME_OK) +- rc = fcommit(commit_ctx, commit_info->p); +- else +- ctx->stats.generic_error++; +- +- if (rc == BCME_OK) { +- ctx->stats.pkt2bus++; +- if (commit_info->ac_fifo_credit_spent) { +- ctx->stats.send_pkts[ac]++; +- WLFC_HOST_FIFO_CREDIT_INC_SENTCTRS(ctx, ac); +- } +- } else if (rc == BCME_NORESOURCE) +- rc = BCME_ERROR; +- else { +- /* +- bus commit has failed, rollback. +- - remove wl-header for a delayed packet +- - save wl-header header for suppressed packets +- */ +- rc = _dhd_wlfc_rollback_packet_toq(ctx, commit_info->p, +- (commit_info->pkt_type), hslot); +- +- rc = BCME_ERROR; +- } +- +- return rc; +-} +- +-int +-dhd_wlfc_commit_packets(void* state, f_commitpkt_t fcommit, void* commit_ctx, void *pktbuf) +-{ +- int ac; +- int credit; +- int rc; +- dhd_wlfc_commit_info_t commit_info; +- athost_wl_status_info_t* ctx = (athost_wl_status_info_t*)state; +- int credit_count = 0; +- int bus_retry_count = 0; +- uint8 ac_available = 0; /* Bitmask for 4 ACs + BC/MC */ +- +- if ((state == NULL) || +- (fcommit == NULL)) { +- WLFC_DBGMESG(("Error: %s():%d\n", __FUNCTION__, __LINE__)); +- return BCME_BADARG; +- } +- +- memset(&commit_info, 0, sizeof(commit_info)); +- +- /* +- Commit packets for regular AC traffic. Higher priority first. +- First, use up FIFO credits available to each AC. Based on distribution +- and credits left, borrow from other ACs as applicable +- +- -NOTE: +- If the bus between the host and firmware is overwhelmed by the +- traffic from host, it is possible that higher priority traffic +- starves the lower priority queue. If that occurs often, we may +- have to employ weighted round-robin or ucode scheme to avoid +- low priority packet starvation. +- */ +- +- if (pktbuf) { +- ac = DHD_PKTTAG_FIFO(PKTTAG(pktbuf)); +- if (ETHER_ISMULTI(DHD_PKTTAG_DSTN(PKTTAG(pktbuf)))) { +- ASSERT(ac == AC_COUNT); +- commit_info.needs_hdr = 1; +- commit_info.mac_entry = NULL; +- commit_info.pkt_type = eWLFC_PKTTYPE_NEW; +- commit_info.p = pktbuf; +- if (ctx->FIFO_credit[ac]) { +- rc = _dhd_wlfc_handle_packet_commit(ctx, ac, &commit_info, +- fcommit, commit_ctx); +- +- /* Bus commits may fail (e.g. flow control); abort after retries */ +- if (rc == BCME_OK) { +- if (commit_info.ac_fifo_credit_spent) { +- (void) _dhd_wlfc_borrow_credit(ctx, +- ac_available, ac); +- credit_count--; +- } +- } else { +- bus_retry_count++; +- if (bus_retry_count >= BUS_RETRIES) { +- DHD_ERROR((" %s: bus error %d\n", +- __FUNCTION__, rc)); +- return rc; +- } +- } +- } +- } +- else { +- /* en-queue the packets to respective queue. */ +- rc = _dhd_wlfc_enque_delayq(ctx, pktbuf, ac); +- } +- } +- +- for (ac = AC_COUNT; ac >= 0; ac--) { +- +- bool bQueueIdle = TRUE; +- +- /* packets from delayQ with less priority are fresh and they'd need header and +- * have no MAC entry +- */ +- commit_info.needs_hdr = 1; +- commit_info.mac_entry = NULL; +- commit_info.pkt_type = eWLFC_PKTTYPE_NEW; +- +- for (credit = 0; credit < ctx->FIFO_credit[ac];) { +- commit_info.p = _dhd_wlfc_deque_delayedq(ctx, ac, +- &(commit_info.ac_fifo_credit_spent), +- &(commit_info.needs_hdr), +- &(commit_info.mac_entry)); +- +- if (commit_info.p == NULL) +- break; +- +- bQueueIdle = FALSE; +- +- commit_info.pkt_type = (commit_info.needs_hdr) ? eWLFC_PKTTYPE_DELAYED : +- eWLFC_PKTTYPE_SUPPRESSED; +- +- rc = _dhd_wlfc_handle_packet_commit(ctx, ac, &commit_info, +- fcommit, commit_ctx); +- +- /* Bus commits may fail (e.g. flow control); abort after retries */ +- if (rc == BCME_OK) { +- if (commit_info.ac_fifo_credit_spent) { +- credit++; +- } +- } +- else { +- bus_retry_count++; +- if (bus_retry_count >= BUS_RETRIES) { +- DHD_ERROR(("%s: bus error %d\n", __FUNCTION__, rc)); +- ctx->FIFO_credit[ac] -= credit; +- return rc; +- } +- } +- } +- +- ctx->FIFO_credit[ac] -= credit; +- +- +- /* If no pkts can be dequed, the credit can be borrowed */ +- if (bQueueIdle) { +- ac_available |= (1 << ac); +- credit_count += ctx->FIFO_credit[ac]; +- } +- } +- +- /* We borrow only for AC_BE and only if no other traffic seen for DEFER_PERIOD +- +- Note that (ac_available & WLFC_AC_BE_TRAFFIC_ONLY) is done to: +- a) ignore BC/MC for deferring borrow +- b) ignore AC_BE being available along with other ACs +- (this should happen only for pure BC/MC traffic) +- +- i.e. AC_VI, AC_VO, AC_BK all MUST be available (i.e. no traffic) and +- we do not care if AC_BE and BC/MC are available or not +- */ +- if ((ac_available & WLFC_AC_BE_TRAFFIC_ONLY) == WLFC_AC_BE_TRAFFIC_ONLY) { +- +- if (ctx->allow_credit_borrow) { +- ac = 1; /* Set ac to AC_BE and borrow credits */ +- } +- else { +- int delta; +- int curr_t = OSL_SYSUPTIME(); +- +- if (curr_t > ctx->borrow_defer_timestamp) +- delta = curr_t - ctx->borrow_defer_timestamp; +- else +- delta = 0xffffffff + curr_t - ctx->borrow_defer_timestamp; +- +- if (delta >= WLFC_BORROW_DEFER_PERIOD_MS) { +- /* Reset borrow but defer to next iteration (defensive borrowing) */ +- ctx->allow_credit_borrow = TRUE; +- ctx->borrow_defer_timestamp = 0; +- } +- return BCME_OK; +- } +- } +- else { +- /* If we have multiple AC traffic, turn off borrowing, mark time and bail out */ +- ctx->allow_credit_borrow = FALSE; +- ctx->borrow_defer_timestamp = OSL_SYSUPTIME(); +- return BCME_OK; +- } +- +- /* At this point, borrow all credits only for "ac" (which should be set above to AC_BE) +- Generically use "ac" only in case we extend to all ACs in future +- */ +- for (; (credit_count > 0);) { +- +- commit_info.p = _dhd_wlfc_deque_delayedq(ctx, ac, +- &(commit_info.ac_fifo_credit_spent), +- &(commit_info.needs_hdr), +- &(commit_info.mac_entry)); +- if (commit_info.p == NULL) +- break; +- +- commit_info.pkt_type = (commit_info.needs_hdr) ? eWLFC_PKTTYPE_DELAYED : +- eWLFC_PKTTYPE_SUPPRESSED; +- +- rc = _dhd_wlfc_handle_packet_commit(ctx, ac, &commit_info, +- fcommit, commit_ctx); +- +- /* Bus commits may fail (e.g. flow control); abort after retries */ +- if (rc == BCME_OK) { +- if (commit_info.ac_fifo_credit_spent) { +- (void) _dhd_wlfc_borrow_credit(ctx, ac_available, ac); +- credit_count--; +- } +- } +- else { +- bus_retry_count++; +- if (bus_retry_count >= BUS_RETRIES) { +- DHD_ERROR(("%s: bus error %d\n", __FUNCTION__, rc)); +- return rc; +- } +- } +- } +- return BCME_OK; +-} +- +-static uint8 +-dhd_wlfc_find_mac_desc_id_from_mac(dhd_pub_t *dhdp, uint8* ea) +-{ +- wlfc_mac_descriptor_t* table = +- ((athost_wl_status_info_t*)dhdp->wlfc_state)->destination_entries.nodes; +- uint8 table_index; +- +- if (ea != NULL) { +- for (table_index = 0; table_index < WLFC_MAC_DESC_TABLE_SIZE; table_index++) { +- if ((memcmp(ea, &table[table_index].ea[0], ETHER_ADDR_LEN) == 0) && +- table[table_index].occupied) +- return table_index; +- } +- } +- return WLFC_MAC_DESC_ID_INVALID; +-} +- +-void +-dhd_wlfc_txcomplete(dhd_pub_t *dhd, void *txp, bool success) +-{ +- athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) +- dhd->wlfc_state; +- void* p; +- int fifo_id; +- +- if (DHD_PKTTAG_SIGNALONLY(PKTTAG(txp))) { +-#ifdef PROP_TXSTATUS_DEBUG +- wlfc->stats.signal_only_pkts_freed++; +-#endif +- /* is this a signal-only packet? */ +- if (success) +- PKTFREE(wlfc->osh, txp, TRUE); +- return; +- } +- if (!success) { +- WLFC_DBGMESG(("At: %s():%d, bus_complete() failure for %p, htod_tag:0x%08x\n", +- __FUNCTION__, __LINE__, txp, DHD_PKTTAG_H2DTAG(PKTTAG(txp)))); +- dhd_wlfc_hanger_poppkt(wlfc->hanger, WLFC_PKTID_HSLOT_GET(DHD_PKTTAG_H2DTAG +- (PKTTAG(txp))), &p, 1); +- +- /* indicate failure and free the packet */ +- dhd_txcomplete(dhd, txp, FALSE); +- +- /* return the credit, if necessary */ +- if (DHD_PKTTAG_CREDITCHECK(PKTTAG(txp))) { +- int lender, credit_returned = 0; /* Note that borrower is fifo_id */ +- +- fifo_id = DHD_PKTTAG_FIFO(PKTTAG(txp)); +- +- /* Return credits to highest priority lender first */ +- for (lender = AC_COUNT; lender >= 0; lender--) { +- if (wlfc->credits_borrowed[fifo_id][lender] > 0) { +- wlfc->FIFO_credit[lender]++; +- wlfc->credits_borrowed[fifo_id][lender]--; +- credit_returned = 1; +- break; +- } +- } +- +- if (!credit_returned) { +- wlfc->FIFO_credit[fifo_id]++; +- } +- } +- +- PKTFREE(wlfc->osh, txp, TRUE); +- } +- return; +-} +- +-static int +-dhd_wlfc_compressed_txstatus_update(dhd_pub_t *dhd, uint8* pkt_info, uint8 len) +-{ +- uint8 status_flag; +- uint32 status; +- int ret; +- int remove_from_hanger = 1; +- void* pktbuf; +- uint8 fifo_id; +- uint8 count = 0; +- uint32 status_g; +- uint32 hslot, hcnt; +- wlfc_mac_descriptor_t* entry = NULL; +- athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) +- dhd->wlfc_state; +- +- memcpy(&status, pkt_info, sizeof(uint32)); +- status_flag = WL_TXSTATUS_GET_FLAGS(status); +- status_g = status & 0xff000000; +- hslot = (status & 0x00ffff00) >> 8; +- hcnt = status & 0xff; +- len = pkt_info[4]; +- +- wlfc->stats.txstatus_in++; +- +- if (status_flag == WLFC_CTL_PKTFLAG_DISCARD) { +- wlfc->stats.pkt_freed++; +- } +- +- else if (status_flag == WLFC_CTL_PKTFLAG_D11SUPPRESS) { +- wlfc->stats.d11_suppress++; +- remove_from_hanger = 0; +- } +- +- else if (status_flag == WLFC_CTL_PKTFLAG_WLSUPPRESS) { +- wlfc->stats.wl_suppress++; +- remove_from_hanger = 0; +- } +- +- else if (status_flag == WLFC_CTL_PKTFLAG_TOSSED_BYWLC) { +- wlfc->stats.wlc_tossed_pkts++; +- } +- while (count < len) { +- status = (status_g << 24) | (hslot << 8) | (hcnt); +- count++; +- hslot++; +- hcnt++; +- +- ret = dhd_wlfc_hanger_poppkt(wlfc->hanger, +- WLFC_PKTID_HSLOT_GET(status), &pktbuf, remove_from_hanger); +- if (ret != BCME_OK) { +- /* do something */ +- continue; +- } +- +- entry = _dhd_wlfc_find_table_entry(wlfc, pktbuf); +- +- if (!remove_from_hanger) { +- /* this packet was suppressed */ +- if (!entry->suppressed || entry->generation != WLFC_PKTID_GEN(status)) { +- entry->suppressed = TRUE; +- entry->suppress_count = pktq_mlen(&entry->psq, +- NBITVAL((WL_TXSTATUS_GET_FIFO(status) << 1) + 1)); +- entry->suppr_transit_count = entry->transit_count; +- } +- entry->generation = WLFC_PKTID_GEN(status); +- } +- +-#ifdef PROP_TXSTATUS_DEBUG +- { +- uint32 new_t = OSL_SYSUPTIME(); +- uint32 old_t; +- uint32 delta; +- old_t = ((wlfc_hanger_t*)(wlfc->hanger))->items[ +- WLFC_PKTID_HSLOT_GET(status)].push_time; +- +- +- wlfc->stats.latency_sample_count++; +- if (new_t > old_t) +- delta = new_t - old_t; +- else +- delta = 0xffffffff + new_t - old_t; +- wlfc->stats.total_status_latency += delta; +- wlfc->stats.latency_most_recent = delta; +- +- wlfc->stats.deltas[wlfc->stats.idx_delta++] = delta; +- if (wlfc->stats.idx_delta == sizeof(wlfc->stats.deltas)/sizeof(uint32)) +- wlfc->stats.idx_delta = 0; +- } +-#endif /* PROP_TXSTATUS_DEBUG */ +- +- fifo_id = DHD_PKTTAG_FIFO(PKTTAG(pktbuf)); +- +- /* pick up the implicit credit from this packet */ +- if (DHD_PKTTAG_CREDITCHECK(PKTTAG(pktbuf))) { +- if (wlfc->proptxstatus_mode == WLFC_FCMODE_IMPLIED_CREDIT) { +- +- int lender, credit_returned = 0; /* Note that borrower is fifo_id */ +- +- /* Return credits to highest priority lender first */ +- for (lender = AC_COUNT; lender >= 0; lender--) { +- if (wlfc->credits_borrowed[fifo_id][lender] > 0) { +- wlfc->FIFO_credit[lender]++; +- wlfc->credits_borrowed[fifo_id][lender]--; +- credit_returned = 1; +- break; +- } +- } +- +- if (!credit_returned) { +- wlfc->FIFO_credit[fifo_id]++; +- } +- } +- } +- else { +- /* +- if this packet did not count against FIFO credit, it must have +- taken a requested_credit from the destination entry (for pspoll etc.) +- */ +- if (!entry) { +- +- entry = _dhd_wlfc_find_table_entry(wlfc, pktbuf); +- } +- if (!DHD_PKTTAG_ONETIMEPKTRQST(PKTTAG(pktbuf))) +- entry->requested_credit++; +-#ifdef PROP_TXSTATUS_DEBUG +- entry->dstncredit_acks++; +-#endif +- } +- if ((status_flag == WLFC_CTL_PKTFLAG_D11SUPPRESS) || +- (status_flag == WLFC_CTL_PKTFLAG_WLSUPPRESS)) { +- +- ret = _dhd_wlfc_enque_suppressed(wlfc, fifo_id, pktbuf); +- if (ret != BCME_OK) { +- /* delay q is full, drop this packet */ +- dhd_wlfc_hanger_poppkt(wlfc->hanger, WLFC_PKTID_HSLOT_GET(status), +- &pktbuf, 1); +- +- /* indicate failure and free the packet */ +- dhd_txcomplete(dhd, pktbuf, FALSE); +- entry->transit_count--; +- DHD_WLFC_QMON_COMPLETE(entry); +- /* packet is transmitted Successfully by dongle +- * after first suppress. +- */ +- if (entry->suppressed) { +- entry->suppr_transit_count--; +- } +- PKTFREE(wlfc->osh, pktbuf, TRUE); +- } else { +- /* Mark suppressed to avoid a double free during wlfc cleanup */ +- +- dhd_wlfc_hanger_mark_suppressed(wlfc->hanger, +- WLFC_PKTID_HSLOT_GET(status), WLFC_PKTID_GEN(status)); +- entry->suppress_count++; +- } +- } +- else { +- dhd_txcomplete(dhd, pktbuf, TRUE); +- entry->transit_count--; +- DHD_WLFC_QMON_COMPLETE(entry); +- +- /* This packet is transmitted Successfully by dongle +- * even after first suppress. +- */ +- if (entry->suppressed) { +- entry->suppr_transit_count--; +- } +- /* free the packet */ +- PKTFREE(wlfc->osh, pktbuf, TRUE); +- } +- } +- return BCME_OK; +-} +- +-/* Handle discard or suppress indication */ +-static int +-dhd_wlfc_txstatus_update(dhd_pub_t *dhd, uint8* pkt_info) +-{ +- uint8 status_flag; +- uint32 status; +- int ret; +- int remove_from_hanger = 1; +- void* pktbuf; +- uint8 fifo_id; +- wlfc_mac_descriptor_t* entry = NULL; +- athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) +- dhd->wlfc_state; +- +- memcpy(&status, pkt_info, sizeof(uint32)); +- status_flag = WL_TXSTATUS_GET_FLAGS(status); +- wlfc->stats.txstatus_in++; +- +- if (status_flag == WLFC_CTL_PKTFLAG_DISCARD) { +- wlfc->stats.pkt_freed++; +- } +- +- else if (status_flag == WLFC_CTL_PKTFLAG_D11SUPPRESS) { +- wlfc->stats.d11_suppress++; +- remove_from_hanger = 0; +- } +- +- else if (status_flag == WLFC_CTL_PKTFLAG_WLSUPPRESS) { +- wlfc->stats.wl_suppress++; +- remove_from_hanger = 0; +- } +- +- else if (status_flag == WLFC_CTL_PKTFLAG_TOSSED_BYWLC) { +- wlfc->stats.wlc_tossed_pkts++; +- } +- +- ret = dhd_wlfc_hanger_poppkt(wlfc->hanger, +- WLFC_PKTID_HSLOT_GET(status), &pktbuf, remove_from_hanger); +- if (ret != BCME_OK) { +- /* do something */ +- return ret; +- } +- +- entry = _dhd_wlfc_find_table_entry(wlfc, pktbuf); +- +- if (!remove_from_hanger) { +- /* this packet was suppressed */ +- if (!entry->suppressed || entry->generation != WLFC_PKTID_GEN(status)) { +- entry->suppressed = TRUE; +- entry->suppress_count = pktq_mlen(&entry->psq, +- NBITVAL((WL_TXSTATUS_GET_FIFO(status) << 1) + 1)); +- entry->suppr_transit_count = entry->transit_count; +- } +- entry->generation = WLFC_PKTID_GEN(status); +- } +- +-#ifdef PROP_TXSTATUS_DEBUG +- { +- uint32 new_t = OSL_SYSUPTIME(); +- uint32 old_t; +- uint32 delta; +- old_t = ((wlfc_hanger_t*)(wlfc->hanger))->items[ +- WLFC_PKTID_HSLOT_GET(status)].push_time; +- +- +- wlfc->stats.latency_sample_count++; +- if (new_t > old_t) +- delta = new_t - old_t; +- else +- delta = 0xffffffff + new_t - old_t; +- wlfc->stats.total_status_latency += delta; +- wlfc->stats.latency_most_recent = delta; +- +- wlfc->stats.deltas[wlfc->stats.idx_delta++] = delta; +- if (wlfc->stats.idx_delta == sizeof(wlfc->stats.deltas)/sizeof(uint32)) +- wlfc->stats.idx_delta = 0; +- } +-#endif /* PROP_TXSTATUS_DEBUG */ +- +- fifo_id = DHD_PKTTAG_FIFO(PKTTAG(pktbuf)); +- +- /* pick up the implicit credit from this packet */ +- if (DHD_PKTTAG_CREDITCHECK(PKTTAG(pktbuf))) { +- if (wlfc->proptxstatus_mode == WLFC_FCMODE_IMPLIED_CREDIT) { +- +- int lender, credit_returned = 0; /* Note that borrower is fifo_id */ +- +- /* Return credits to highest priority lender first */ +- for (lender = AC_COUNT; lender >= 0; lender--) { +- if (wlfc->credits_borrowed[fifo_id][lender] > 0) { +- wlfc->FIFO_credit[lender]++; +- wlfc->credits_borrowed[fifo_id][lender]--; +- credit_returned = 1; +- break; +- } +- } +- +- if (!credit_returned) { +- wlfc->FIFO_credit[fifo_id]++; +- } +- } +- } +- else { +- /* +- if this packet did not count against FIFO credit, it must have +- taken a requested_credit from the destination entry (for pspoll etc.) +- */ +- if (!entry) { +- +- entry = _dhd_wlfc_find_table_entry(wlfc, pktbuf); +- } +- if (!DHD_PKTTAG_ONETIMEPKTRQST(PKTTAG(pktbuf))) +- entry->requested_credit++; +-#ifdef PROP_TXSTATUS_DEBUG +- entry->dstncredit_acks++; +-#endif +- } +- if ((status_flag == WLFC_CTL_PKTFLAG_D11SUPPRESS) || +- (status_flag == WLFC_CTL_PKTFLAG_WLSUPPRESS)) { +- +- ret = _dhd_wlfc_enque_suppressed(wlfc, fifo_id, pktbuf); +- if (ret != BCME_OK) { +- /* delay q is full, drop this packet */ +- dhd_wlfc_hanger_poppkt(wlfc->hanger, WLFC_PKTID_HSLOT_GET(status), +- &pktbuf, 1); +- +- /* indicate failure and free the packet */ +- dhd_txcomplete(dhd, pktbuf, FALSE); +- entry->transit_count--; +- DHD_WLFC_QMON_COMPLETE(entry); +- /* This packet is transmitted Successfully by +- * dongle even after first suppress. +- */ +- if (entry->suppressed) { +- entry->suppr_transit_count--; +- } +- PKTFREE(wlfc->osh, pktbuf, TRUE); +- } else { +- /* Mark suppressed to avoid a double free during wlfc cleanup */ +- +- dhd_wlfc_hanger_mark_suppressed(wlfc->hanger, +- WLFC_PKTID_HSLOT_GET(status), WLFC_PKTID_GEN(status)); +- entry->suppress_count++; +- } +- } +- else { +- dhd_txcomplete(dhd, pktbuf, TRUE); +- entry->transit_count--; +- DHD_WLFC_QMON_COMPLETE(entry); +- +- /* This packet is transmitted Successfully by dongle even after first suppress. */ +- if (entry->suppressed) { +- entry->suppr_transit_count--; +- } +- /* free the packet */ +- PKTFREE(wlfc->osh, pktbuf, TRUE); +- } +- return BCME_OK; +-} +- +-static int +-dhd_wlfc_fifocreditback_indicate(dhd_pub_t *dhd, uint8* credits) +-{ +- int i; +- athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) +- dhd->wlfc_state; +- for (i = 0; i < WLFC_CTL_VALUE_LEN_FIFO_CREDITBACK; i++) { +-#ifdef PROP_TXSTATUS_DEBUG +- wlfc->stats.fifo_credits_back[i] += credits[i]; +-#endif +- /* update FIFO credits */ +- if (wlfc->proptxstatus_mode == WLFC_FCMODE_EXPLICIT_CREDIT) +- { +- int lender; /* Note that borrower is i */ +- +- /* Return credits to highest priority lender first */ +- for (lender = AC_COUNT; (lender >= 0) && (credits[i] > 0); lender--) { +- if (wlfc->credits_borrowed[i][lender] > 0) { +- if (credits[i] >= wlfc->credits_borrowed[i][lender]) { +- credits[i] -= wlfc->credits_borrowed[i][lender]; +- wlfc->FIFO_credit[lender] += +- wlfc->credits_borrowed[i][lender]; +- wlfc->credits_borrowed[i][lender] = 0; +- } +- else { +- wlfc->credits_borrowed[i][lender] -= credits[i]; +- wlfc->FIFO_credit[lender] += credits[i]; +- credits[i] = 0; +- } +- } +- } +- +- /* If we have more credits left over, these must belong to the AC */ +- if (credits[i] > 0) { +- wlfc->FIFO_credit[i] += credits[i]; +- } +- } +- } +- +- return BCME_OK; +-} +- +-static int +-dhd_wlfc_dbg_senum_check(dhd_pub_t *dhd, uint8 *value) +-{ +- uint32 timestamp; +- +- (void)dhd; +- +- bcopy(&value[2], ×tamp, sizeof(uint32)); +- DHD_INFO(("RXPKT: SEQ: %d, timestamp %d\n", value[1], timestamp)); +- return BCME_OK; +-} +- +- +-static int +-dhd_wlfc_rssi_indicate(dhd_pub_t *dhd, uint8* rssi) +-{ +- (void)dhd; +- (void)rssi; +- return BCME_OK; +-} +- +-static int +-dhd_wlfc_mac_table_update(dhd_pub_t *dhd, uint8* value, uint8 type) +-{ +- int rc; +- athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) +- dhd->wlfc_state; +- wlfc_mac_descriptor_t* table; +- uint8 existing_index; +- uint8 table_index; +- uint8 ifid; +- uint8* ea; +- +- WLFC_DBGMESG(("%s(), mac [%02x:%02x:%02x:%02x:%02x:%02x],%s,idx:%d,id:0x%02x\n", +- __FUNCTION__, value[2], value[3], value[4], value[5], value[6], value[7], +- ((type == WLFC_CTL_TYPE_MACDESC_ADD) ? "ADD":"DEL"), +- WLFC_MAC_DESC_GET_LOOKUP_INDEX(value[0]), value[0])); +- +- table = wlfc->destination_entries.nodes; +- table_index = WLFC_MAC_DESC_GET_LOOKUP_INDEX(value[0]); +- ifid = value[1]; +- ea = &value[2]; +- +- if (type == WLFC_CTL_TYPE_MACDESC_ADD) { +- existing_index = dhd_wlfc_find_mac_desc_id_from_mac(dhd, &value[2]); +- if (existing_index == WLFC_MAC_DESC_ID_INVALID) { +- /* this MAC entry does not exist, create one */ +- if (!table[table_index].occupied) { +- table[table_index].mac_handle = value[0]; +- rc = _dhd_wlfc_mac_entry_update(wlfc, &table[table_index], +- eWLFC_MAC_ENTRY_ACTION_ADD, ifid, +- wlfc->destination_entries.interfaces[ifid].iftype, +- ea); +- } +- else { +- /* the space should have been empty, but it's not */ +- wlfc->stats.mac_update_failed++; +- } +- } +- else { +- /* +- there is an existing entry, move it to new index +- if necessary. +- */ +- if (existing_index != table_index) { +- /* if we already have an entry, free the old one */ +- table[existing_index].occupied = 0; +- table[existing_index].state = WLFC_STATE_CLOSE; +- table[existing_index].requested_credit = 0; +- table[existing_index].interface_id = 0; +- /* enable after packets are queued-deqeued properly. +- pktq_flush(dhd->osh, &table[existing_index].psq, FALSE, NULL, 0); +- */ +- } +- } +- } +- if (type == WLFC_CTL_TYPE_MACDESC_DEL) { +- if (table[table_index].occupied) { +- rc = _dhd_wlfc_mac_entry_update(wlfc, &table[table_index], +- eWLFC_MAC_ENTRY_ACTION_DEL, ifid, +- wlfc->destination_entries.interfaces[ifid].iftype, +- ea); +- } +- else { +- /* the space should have been occupied, but it's not */ +- wlfc->stats.mac_update_failed++; +- } +- } +- BCM_REFERENCE(rc); +- return BCME_OK; +-} +- +-static int +-dhd_wlfc_psmode_update(dhd_pub_t *dhd, uint8* value, uint8 type) +-{ +- /* Handle PS on/off indication */ +- athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) +- dhd->wlfc_state; +- wlfc_mac_descriptor_t* table; +- wlfc_mac_descriptor_t* desc; +- uint8 mac_handle = value[0]; +- int i; +- +- table = wlfc->destination_entries.nodes; +- desc = &table[WLFC_MAC_DESC_GET_LOOKUP_INDEX(mac_handle)]; +- if (desc->occupied) { +- /* a fresh PS mode should wipe old ps credits? */ +- desc->requested_credit = 0; +- if (type == WLFC_CTL_TYPE_MAC_OPEN) { +- desc->state = WLFC_STATE_OPEN; +- DHD_WLFC_CTRINC_MAC_OPEN(desc); +- } +- else { +- desc->state = WLFC_STATE_CLOSE; +- DHD_WLFC_CTRINC_MAC_CLOSE(desc); +- /* +- Indicate to firmware if there is any traffic pending. +- */ +- for (i = AC_BE; i < AC_COUNT; i++) { +- _dhd_wlfc_traffic_pending_check(wlfc, desc, i); +- } +- } +- } +- else { +- wlfc->stats.psmode_update_failed++; +- } +- return BCME_OK; +-} +- +-static int +-dhd_wlfc_interface_update(dhd_pub_t *dhd, uint8* value, uint8 type) +-{ +- /* Handle PS on/off indication */ +- athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) +- dhd->wlfc_state; +- wlfc_mac_descriptor_t* table; +- uint8 if_id = value[0]; +- +- if (if_id < WLFC_MAX_IFNUM) { +- table = wlfc->destination_entries.interfaces; +- if (table[if_id].occupied) { +- if (type == WLFC_CTL_TYPE_INTERFACE_OPEN) { +- table[if_id].state = WLFC_STATE_OPEN; +- /* WLFC_DBGMESG(("INTERFACE[%d] OPEN\n", if_id)); */ +- } +- else { +- table[if_id].state = WLFC_STATE_CLOSE; +- /* WLFC_DBGMESG(("INTERFACE[%d] CLOSE\n", if_id)); */ +- } +- return BCME_OK; +- } +- } +- wlfc->stats.interface_update_failed++; +- +- return BCME_OK; +-} +- +-static int +-dhd_wlfc_credit_request(dhd_pub_t *dhd, uint8* value) +-{ +- athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) +- dhd->wlfc_state; +- wlfc_mac_descriptor_t* table; +- wlfc_mac_descriptor_t* desc; +- uint8 mac_handle; +- uint8 credit; +- +- table = wlfc->destination_entries.nodes; +- mac_handle = value[1]; +- credit = value[0]; +- +- desc = &table[WLFC_MAC_DESC_GET_LOOKUP_INDEX(mac_handle)]; +- if (desc->occupied) { +- desc->requested_credit = credit; +- +- desc->ac_bitmap = value[2]; +- } +- else { +- wlfc->stats.credit_request_failed++; +- } +- return BCME_OK; +-} +- +-static int +-dhd_wlfc_packet_request(dhd_pub_t *dhd, uint8* value) +-{ +- athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) +- dhd->wlfc_state; +- wlfc_mac_descriptor_t* table; +- wlfc_mac_descriptor_t* desc; +- uint8 mac_handle; +- uint8 packet_count; +- +- table = wlfc->destination_entries.nodes; +- mac_handle = value[1]; +- packet_count = value[0]; +- +- desc = &table[WLFC_MAC_DESC_GET_LOOKUP_INDEX(mac_handle)]; +- if (desc->occupied) { +- desc->requested_packet = packet_count; +- +- desc->ac_bitmap = value[2]; +- } +- else { +- wlfc->stats.packet_request_failed++; +- } +- return BCME_OK; +-} +- +-static void +-dhd_wlfc_reorderinfo_indicate(uint8 *val, uint8 len, uchar *info_buf, uint *info_len) +-{ +- if (info_len) { +- if (info_buf) { +- bcopy(val, info_buf, len); +- *info_len = len; +- } +- else +- *info_len = 0; +- } +-} +- +-int +-dhd_wlfc_parse_header_info(dhd_pub_t *dhd, void* pktbuf, int tlv_hdr_len, uchar *reorder_info_buf, +- uint *reorder_info_len) +-{ +- uint8 type, len; +- uint8* value; +- uint8* tmpbuf; +- uint16 remainder = tlv_hdr_len; +- uint16 processed = 0; +- athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) +- dhd->wlfc_state; +- tmpbuf = (uint8*)PKTDATA(dhd->osh, pktbuf); +- if (remainder) { +- while ((processed < (WLFC_MAX_PENDING_DATALEN * 2)) && (remainder > 0)) { +- type = tmpbuf[processed]; +- if (type == WLFC_CTL_TYPE_FILLER) { +- remainder -= 1; +- processed += 1; +- continue; +- } +- +- len = tmpbuf[processed + 1]; +- value = &tmpbuf[processed + 2]; +- +- if (remainder < (2 + len)) +- break; +- +- remainder -= 2 + len; +- processed += 2 + len; +- if (type == WLFC_CTL_TYPE_TXSTATUS) +- dhd_wlfc_txstatus_update(dhd, value); +- if (type == WLFC_CTL_TYPE_COMP_TXSTATUS) +- dhd_wlfc_compressed_txstatus_update(dhd, value, len); +- +- else if (type == WLFC_CTL_TYPE_HOST_REORDER_RXPKTS) +- dhd_wlfc_reorderinfo_indicate(value, len, reorder_info_buf, +- reorder_info_len); +- else if (type == WLFC_CTL_TYPE_FIFO_CREDITBACK) +- dhd_wlfc_fifocreditback_indicate(dhd, value); +- +- else if (type == WLFC_CTL_TYPE_RSSI) +- dhd_wlfc_rssi_indicate(dhd, value); +- +- else if (type == WLFC_CTL_TYPE_MAC_REQUEST_CREDIT) +- dhd_wlfc_credit_request(dhd, value); +- +- else if (type == WLFC_CTL_TYPE_MAC_REQUEST_PACKET) +- dhd_wlfc_packet_request(dhd, value); +- +- else if ((type == WLFC_CTL_TYPE_MAC_OPEN) || +- (type == WLFC_CTL_TYPE_MAC_CLOSE)) +- dhd_wlfc_psmode_update(dhd, value, type); +- +- else if ((type == WLFC_CTL_TYPE_MACDESC_ADD) || +- (type == WLFC_CTL_TYPE_MACDESC_DEL)) +- dhd_wlfc_mac_table_update(dhd, value, type); +- +- else if (type == WLFC_CTL_TYPE_TRANS_ID) +- dhd_wlfc_dbg_senum_check(dhd, value); +- +- else if ((type == WLFC_CTL_TYPE_INTERFACE_OPEN) || +- (type == WLFC_CTL_TYPE_INTERFACE_CLOSE)) { +- dhd_wlfc_interface_update(dhd, value, type); +- } +- } +- if (remainder != 0) { +- /* trouble..., something is not right */ +- wlfc->stats.tlv_parse_failed++; +- } +- } +- return BCME_OK; +-} +- +-int +-dhd_wlfc_init(dhd_pub_t *dhd) +-{ +- char iovbuf[12]; /* Room for "tlv" + '\0' + parameter */ +- /* enable all signals & indicate host proptxstatus logic is active */ +- uint32 tlv = dhd->wlfc_enabled? +- WLFC_FLAGS_RSSI_SIGNALS | +- WLFC_FLAGS_XONXOFF_SIGNALS | +- WLFC_FLAGS_CREDIT_STATUS_SIGNALS | +- WLFC_FLAGS_HOST_PROPTXSTATUS_ACTIVE | +- WLFC_FLAGS_HOST_RXRERODER_ACTIVE : 0; +- /* WLFC_FLAGS_HOST_PROPTXSTATUS_ACTIVE | WLFC_FLAGS_HOST_RXRERODER_ACTIVE : 0; */ +- +- +- /* +- try to enable/disable signaling by sending "tlv" iovar. if that fails, +- fallback to no flow control? Print a message for now. +- */ +- +- /* enable proptxtstatus signaling by default */ +- bcm_mkiovar("tlv", (char *)&tlv, 4, iovbuf, sizeof(iovbuf)); +- if (dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0) < 0) { +- DHD_ERROR(("dhd_wlfc_init(): failed to enable/disable bdcv2 tlv signaling\n")); +- } +- else { +- /* +- Leaving the message for now, it should be removed after a while; once +- the tlv situation is stable. +- */ +- DHD_ERROR(("dhd_wlfc_init(): successfully %s bdcv2 tlv signaling, %d\n", +- dhd->wlfc_enabled?"enabled":"disabled", tlv)); +- } +- return BCME_OK; +-} +- +-int +-dhd_wlfc_enable(dhd_pub_t *dhd) +-{ +- int i; +- athost_wl_status_info_t* wlfc; +- +- if (!dhd->wlfc_enabled || dhd->wlfc_state) +- return BCME_OK; +- +- /* allocate space to track txstatus propagated from firmware */ +- dhd->wlfc_state = MALLOC(dhd->osh, sizeof(athost_wl_status_info_t)); +- if (dhd->wlfc_state == NULL) +- return BCME_NOMEM; +- +- /* initialize state space */ +- wlfc = (athost_wl_status_info_t*)dhd->wlfc_state; +- memset(wlfc, 0, sizeof(athost_wl_status_info_t)); +- +- /* remember osh & dhdp */ +- wlfc->osh = dhd->osh; +- wlfc->dhdp = dhd; +- +- wlfc->hanger = +- dhd_wlfc_hanger_create(dhd->osh, WLFC_HANGER_MAXITEMS); +- if (wlfc->hanger == NULL) { +- MFREE(dhd->osh, dhd->wlfc_state, sizeof(athost_wl_status_info_t)); +- dhd->wlfc_state = NULL; +- DHD_ERROR(("Failed to malloc dhd->wlfc_state\n")); +- return BCME_NOMEM; +- } +- +- /* initialize all interfaces to accept traffic */ +- for (i = 0; i < WLFC_MAX_IFNUM; i++) { +- wlfc->hostif_flow_state[i] = OFF; +- } +- +- wlfc->destination_entries.other.state = WLFC_STATE_OPEN; +- /* bc/mc FIFO is always open [credit aside], i.e. b[5] */ +- wlfc->destination_entries.other.ac_bitmap = 0x1f; +- wlfc->destination_entries.other.interface_id = 0; +- +- wlfc->proptxstatus_mode = WLFC_FCMODE_EXPLICIT_CREDIT; +- +- wlfc->allow_credit_borrow = TRUE; +- wlfc->borrow_defer_timestamp = 0; +- +- return BCME_OK; +-} +- +-/* release all packet resources */ +-void +-dhd_wlfc_cleanup(dhd_pub_t *dhd, ifpkt_cb_t fn, int arg) +-{ +- int i; +- int total_entries; +- athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) +- dhd->wlfc_state; +- wlfc_mac_descriptor_t* table; +- wlfc_hanger_t* h; +- int prec; +- void *pkt = NULL; +- struct pktq *txq = NULL; +- if (dhd->wlfc_state == NULL) +- return; +- /* flush bus->txq */ +- txq = dhd_bus_txq(dhd->bus); +- /* any in the hanger? */ +- h = (wlfc_hanger_t*)wlfc->hanger; +- total_entries = sizeof(wlfc->destination_entries)/sizeof(wlfc_mac_descriptor_t); +- /* search all entries, include nodes as well as interfaces */ +- table = (wlfc_mac_descriptor_t*)&wlfc->destination_entries; +- +- for (i = 0; i < total_entries; i++) { +- if (table[i].occupied && (fn == NULL || (arg == table[i].interface_id))) { +- if (table[i].psq.len) { +- WLFC_DBGMESG(("%s(): DELAYQ[%d].len = %d\n", +- __FUNCTION__, i, table[i].psq.len)); +- /* release packets held in DELAYQ */ +- pktq_flush(wlfc->osh, &table[i].psq, TRUE, fn, arg); +- } +- if (fn == NULL) +- table[i].occupied = 0; +- } +- } +- for (prec = 0; prec < txq->num_prec; prec++) { +- pkt = pktq_pdeq_with_fn(txq, prec, fn, arg); +- while (pkt) { +- for (i = 0; i < h->max_items; i++) { +- if (pkt == h->items[i].pkt) { +- if (h->items[i].state == WLFC_HANGER_ITEM_STATE_INUSE) { +- PKTFREE(wlfc->osh, h->items[i].pkt, TRUE); +- h->items[i].state = WLFC_HANGER_ITEM_STATE_FREE; +- } else if (h->items[i].state == +- WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED) { +- /* These are already freed from the psq */ +- h->items[i].state = WLFC_HANGER_ITEM_STATE_FREE; +- } +- break; +- } +- } +- pkt = pktq_pdeq(txq, prec); +- } +- } +- /* flush remained pkt in hanger queue, not in bus->txq */ +- for (i = 0; i < h->max_items; i++) { +- if (h->items[i].state == WLFC_HANGER_ITEM_STATE_INUSE) { +- if (fn == NULL || (*fn)(h->items[i].pkt, arg)) { +- PKTFREE(wlfc->osh, h->items[i].pkt, TRUE); +- h->items[i].state = WLFC_HANGER_ITEM_STATE_FREE; +- } +- } else if (h->items[i].state == WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED) { +- if (fn == NULL || (*fn)(h->items[i].pkt, arg)) { +- /* These are freed from the psq so no need to free again */ +- h->items[i].state = WLFC_HANGER_ITEM_STATE_FREE; +- } +- } +- } +- return; +-} +- +-void +-dhd_wlfc_deinit(dhd_pub_t *dhd) +-{ +- /* cleanup all psq related resources */ +- athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) +- dhd->wlfc_state; +- +- dhd_os_wlfc_block(dhd); +- if (dhd->wlfc_state == NULL) { +- dhd_os_wlfc_unblock(dhd); +- return; +- } +- +-#ifdef PROP_TXSTATUS_DEBUG +- { +- int i; +- wlfc_hanger_t* h = (wlfc_hanger_t*)wlfc->hanger; +- for (i = 0; i < h->max_items; i++) { +- if (h->items[i].state != WLFC_HANGER_ITEM_STATE_FREE) { +- WLFC_DBGMESG(("%s() pkt[%d] = 0x%p, FIFO_credit_used:%d\n", +- __FUNCTION__, i, h->items[i].pkt, +- DHD_PKTTAG_CREDITCHECK(PKTTAG(h->items[i].pkt)))); +- } +- } +- } +-#endif +- /* delete hanger */ +- dhd_wlfc_hanger_delete(dhd->osh, wlfc->hanger); +- +- /* free top structure */ +- MFREE(dhd->osh, dhd->wlfc_state, sizeof(athost_wl_status_info_t)); +- dhd->wlfc_state = NULL; +- dhd_os_wlfc_unblock(dhd); +- +- return; +-} +-#endif /* PROP_TXSTATUS */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/dhd_wlfc.h linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_wlfc.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/dhd_wlfc.h 2014-01-27 01:30:30.101433269 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/dhd_wlfc.h 2014-02-15 00:43:44.792014069 +0100 +@@ -1,5 +1,5 @@ + /* +-* Copyright (C) 1999-2013, Broadcom Corporation ++* Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -18,7 +18,7 @@ + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. +-* $Id: dhd_wlfc.h 398418 2013-04-24 15:18:27Z $ ++* $Id: dhd_wlfc.h 361006 2012-10-05 07:45:51Z $ + * + */ + #ifndef __wlfc_host_driver_definitions_h__ +@@ -27,10 +27,9 @@ + /* 16 bits will provide an absolute max of 65536 slots */ + #define WLFC_HANGER_MAXITEMS 1024 + +-#define WLFC_HANGER_ITEM_STATE_FREE 1 +-#define WLFC_HANGER_ITEM_STATE_INUSE 2 ++#define WLFC_HANGER_ITEM_STATE_FREE 1 ++#define WLFC_HANGER_ITEM_STATE_INUSE 2 + #define WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED 3 +- + #define WLFC_PKTID_HSLOT_MASK 0xffff /* allow 16 bits only */ + #define WLFC_PKTID_HSLOT_SHIFT 8 + +@@ -85,8 +84,8 @@ typedef struct wlfc_hanger { + uint32 failed_to_push; + uint32 failed_to_pop; + uint32 failed_slotfind; +- uint32 slot_pos; + wlfc_hanger_item_t items[1]; ++ uint32 slot_pos; + } wlfc_hanger_t; + + #define WLFC_HANGER_SIZE(n) ((sizeof(wlfc_hanger_t) - \ +@@ -99,9 +98,13 @@ typedef struct wlfc_hanger { + + #define WLFC_PSQ_LEN 2048 + ++#define WLFC_SENDQ_LEN 256 ++ ++ + #define WLFC_FLOWCONTROL_HIWATER (2048 - 256) + #define WLFC_FLOWCONTROL_LOWATER 256 + ++ + typedef struct wlfc_mac_descriptor { + uint8 occupied; + uint8 interface_id; +@@ -125,17 +128,10 @@ typedef struct wlfc_mac_descriptor { + /* 1= send on next opportunity */ + uint8 send_tim_signal; + uint8 mac_handle; +- /* Number of packets in transit for this entry. */ + uint transit_count; +- /* Numbe of suppression to wait before evict from delayQ */ + uint suppr_transit_count; +- /* Used when a new suppress is detected to track the number of +- * packets getting suppressed +- */ + uint suppress_count; +- /* flag. TRUE when in suppress state */ +- uint8 suppressed; +- uint8 deleting; ++ uint8 suppressed; + + #ifdef PROP_TXSTATUS_DEBUG + uint32 dstncredit_sent_packets; +@@ -158,6 +154,7 @@ typedef struct athost_wl_stat_counters { + uint32 tlv_parse_failed; + uint32 rollback; + uint32 rollback_failed; ++ uint32 sendq_full_error; + uint32 delayq_full_error; + uint32 credit_request_failed; + uint32 packet_request_failed; +@@ -182,7 +179,7 @@ typedef struct athost_wl_stat_counters { + uint32 dhd_hdrpulls; + uint32 generic_error; + /* an extra one for bc/mc traffic */ +- uint32 send_pkts[AC_COUNT + 1]; ++ uint32 sendq_pkts[AC_COUNT + 1]; + #ifdef PROP_TXSTATUS_DEBUG + /* all pkt2bus -> txstatus latency accumulated */ + uint32 latency_sample_count; +@@ -241,6 +238,8 @@ typedef struct athost_wl_status_info { + /* Credit borrow counts for each FIFO from each of the other FIFOs */ + int credits_borrowed[AC_COUNT + 2][AC_COUNT + 2]; + ++ struct pktq SENDQ; ++ + /* packet hanger and MAC->handle lookup table */ + void* hanger; + struct { +@@ -275,6 +274,7 @@ typedef struct athost_wl_status_info { + /* Timestamp to compute how long to defer borrowing for */ + uint32 borrow_defer_timestamp; + ++ bool wlfc_locked; + } athost_wl_status_info_t; + + int dhd_wlfc_enable(dhd_pub_t *dhd); +@@ -285,13 +285,4 @@ int dhd_wlfc_event(struct dhd_info *dhd) + int dhd_os_wlfc_block(dhd_pub_t *pub); + int dhd_os_wlfc_unblock(dhd_pub_t *pub); + +-void dhd_wlfc_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf); +-int dhd_wlfc_init(dhd_pub_t *dhd); +-void dhd_wlfc_deinit(dhd_pub_t *dhd); +-int dhd_wlfc_parse_header_info(dhd_pub_t *dhd, void* pktbuf, int tlv_hdr_len, +- uchar *reorder_info_buf, uint *reorder_info_len); +-int dhd_wlfc_commit_packets(void* state, f_commitpkt_t fcommit, +- void* commit_ctx, void *pktbuf); +-void dhd_wlfc_cleanup(dhd_pub_t *dhd, ifpkt_cb_t fn, int arg); +-bool ifpkt_fn(void* p, int ifid); + #endif /* __wlfc_host_driver_definitions_h__ */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/dngl_stats.h linux-sunxi-new/drivers/net/wireless/bcmdhd/dngl_stats.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/dngl_stats.h 2014-01-27 01:30:30.108433411 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/dngl_stats.h 2014-02-15 00:43:44.795014136 +0100 +@@ -2,7 +2,7 @@ + * Common stats definitions for clients of dongle + * ports + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/dngl_wlhdr.h linux-sunxi-new/drivers/net/wireless/bcmdhd/dngl_wlhdr.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/dngl_wlhdr.h 2014-01-27 01:30:30.100433249 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/dngl_wlhdr.h 2014-02-15 00:43:44.792014069 +0100 +@@ -1,7 +1,7 @@ + /* + * Dongle WL Header definitions + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/hndpmu.c linux-sunxi-new/drivers/net/wireless/bcmdhd/hndpmu.c +--- linux-sunxi/drivers/net/wireless/bcmdhd/hndpmu.c 2014-01-27 01:30:30.108433411 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/hndpmu.c 2014-02-15 00:43:44.795014136 +0100 +@@ -2,7 +2,7 @@ + * Misc utility routines for accessing PMU corerev specific features + * of the SiliconBackplane-based Broadcom chips. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -22,16 +22,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: hndpmu.c 414368 2013-07-24 15:00:23Z $ +- */ +- +-/* +- * Note: this file contains PLL/FLL related functions. A chip can contain multiple PLLs/FLLs. +- * However, in the context of this file the baseband ('BB') PLL/FLL is referred to. +- * +- * Throughout this code, the prefixes 'pmu0_', 'pmu1_' and 'pmu2_' are used. +- * They refer to different revisions of the PMU (which is at revision 18 @ Apr 25, 2012) +- * pmu2_ marks the transition from PLL to ADFLL (Digital Frequency Locked Loop) ++ * $Id: hndpmu.c 354194 2012-08-30 08:39:03Z $ + */ + + #include +@@ -125,54 +116,16 @@ static const sdiod_drive_str_t sdiod_dri + {1, 0x1}, + {0, 0x0} }; + +- +-/* +- * SDIO Drive Strength to sel value table for 43143 PMU Rev 17, see Confluence 43143 Toplevel +- * architecture page, section 'PMU Chip Control 1 Register definition', click link to picture +- * BCM43143_sel_sdio_signals.jpg. Valid after PMU Chip Control 0 Register, bit31 (override) has +- * been written '1'. +- */ +-#if !defined(BCM_SDIO_VDDIO) || BCM_SDIO_VDDIO == 33 +- +-static const sdiod_drive_str_t sdiod_drive_strength_tab7_3v3[] = { +- /* note: for 14, 10, 6 and 2mA hw timing is not met according to rtl team */ +- {16, 0x7}, +- {12, 0x5}, +- {8, 0x3}, +- {4, 0x1} }; /* note: 43143 does not support tristate */ +- +-#else +- +-static const sdiod_drive_str_t sdiod_drive_strength_tab7_1v8[] = { +- /* note: for 7, 5, 3 and 1mA hw timing is not met according to rtl team */ +- {8, 0x7}, +- {6, 0x5}, +- {4, 0x3}, +- {2, 0x1} }; /* note: 43143 does not support tristate */ +- +-#endif /* BCM_SDIO_VDDIO */ +- + #define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu)) + +-/** +- * Balance between stable SDIO operation and power consumption is achieved using this function. +- * Note that each drive strength table is for a specific VDDIO of the SDIO pads, ideally this +- * function should read the VDDIO itself to select the correct table. For now it has been solved +- * with the 'BCM_SDIO_VDDIO' preprocessor constant. +- * +- * 'drivestrength': desired pad drive strength in mA. Drive strength of 0 requests tri-state (if +- * hardware supports this), if no hw support drive strength is not programmed. +- */ + void + si_sdiod_drive_strength_init(si_t *sih, osl_t *osh, uint32 drivestrength) + { + chipcregs_t *cc; + uint origidx, intr_val = 0; + sdiod_drive_str_t *str_tab = NULL; +- uint32 str_mask = 0; /* only alter desired bits in PMU chipcontrol 1 register */ ++ uint32 str_mask = 0; + uint32 str_shift = 0; +- uint32 str_ovr_pmuctl = PMU_CHIPCTL0; /* PMU chipcontrol register containing override bit */ +- uint32 str_ovr_pmuval = 0; /* position of bit within this register */ + + if (!(sih->cccaps & CC_CAP_PMU)) { + return; +@@ -220,22 +173,10 @@ si_sdiod_drive_strength_init(si_t *sih, + str_mask = 0x00001800; + str_shift = 11; + break; +- case SDIOD_DRVSTR_KEY(BCM43143_CHIP_ID, 17): +-#if !defined(BCM_SDIO_VDDIO) || BCM_SDIO_VDDIO == 33 +- if (drivestrength >= ARRAYLAST(sdiod_drive_strength_tab7_3v3)->strength) { +- str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab7_3v3; +- } +-#else +- if (drivestrength >= ARRAYLAST(sdiod_drive_strength_tab7_1v8)->strength) { +- str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab7_1v8; +- } +-#endif /* BCM_SDIO_VDDIO */ +- str_mask = 0x00000007; +- str_ovr_pmuval = PMU43143_CC0_SDIO_DRSTR_OVR; +- break; + default: + PMU_MSG(("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n", + bcm_chipname(sih->chip, chn, 8), sih->chiprev, sih->pmurev)); ++ + break; + } + +@@ -252,19 +193,16 @@ si_sdiod_drive_strength_init(si_t *sih, + if (i > 0 && drivestrength > str_tab[i].strength) + i--; + +- W_REG(osh, &cc->chipcontrol_addr, PMU_CHIPCTL1); ++ W_REG(osh, &cc->chipcontrol_addr, 1); + cc_data_temp = R_REG(osh, &cc->chipcontrol_data); + cc_data_temp &= ~str_mask; + cc_data_temp |= str_tab[i].sel << str_shift; + W_REG(osh, &cc->chipcontrol_data, cc_data_temp); +- if (str_ovr_pmuval) { /* enables the selected drive strength */ +- W_REG(osh, &cc->chipcontrol_addr, str_ovr_pmuctl); +- OR_REG(osh, &cc->chipcontrol_data, str_ovr_pmuval); +- } ++ + PMU_MSG(("SDIO: %dmA drive strength requested; set to %dmA\n", + drivestrength, str_tab[i].strength)); + } + + /* Return to original core */ + si_restore_core(sih, origidx, intr_val); +-} /* si_sdiod_drive_strength_init */ ++} +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/aidmp.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/aidmp.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/aidmp.h 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/aidmp.h 2014-02-15 00:43:44.794014114 +0100 +@@ -1,7 +1,7 @@ + /* + * Broadcom AMBA Interconnect definitions. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -21,7 +21,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: aidmp.h 385510 2013-02-15 21:02:07Z $ ++ * $Id: aidmp.h 241182 2011-02-17 21:50:03Z $ + */ + + #ifndef _AIDMP_H +@@ -372,15 +372,4 @@ typedef volatile struct _aidmp { + #define OOB_SEL_OUTEN_B_5 15 + #define OOB_SEL_OUTEN_B_6 23 + +-/* AI_OOBSEL for A/B/C/D, 0-7 */ +-#define AI_OOBSEL_MASK 0x1F +-#define AI_OOBSEL_0_SHIFT 0 +-#define AI_OOBSEL_1_SHIFT 8 +-#define AI_OOBSEL_2_SHIFT 16 +-#define AI_OOBSEL_3_SHIFT 24 +-#define AI_OOBSEL_4_SHIFT 0 +-#define AI_OOBSEL_5_SHIFT 8 +-#define AI_OOBSEL_6_SHIFT 16 +-#define AI_OOBSEL_7_SHIFT 24 +- + #endif /* _AIDMP_H */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/bcmcdc.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcmcdc.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/bcmcdc.h 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcmcdc.h 2014-02-15 00:43:44.794014114 +0100 +@@ -4,7 +4,7 @@ + * + * Definitions subject to change without notice. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/bcm_cfg.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcm_cfg.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/bcm_cfg.h 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcm_cfg.h 2014-02-15 00:43:44.794014114 +0100 +@@ -1,7 +1,7 @@ + /* + * BCM common config options + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -21,7 +21,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: bcm_cfg.h 351867 2012-08-21 18:46:16Z $ ++ * $Id: bcm_cfg.h 294399 2011-11-07 03:31:22Z $ + */ + + #ifndef _bcm_cfg_h_ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/bcmdefs.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcmdefs.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/bcmdefs.h 2014-01-27 01:30:30.101433269 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcmdefs.h 2014-02-15 00:43:44.793014092 +0100 +@@ -1,7 +1,7 @@ + /* + * Misc system wide definitions + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -21,7 +21,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: bcmdefs.h 416231 2013-08-02 07:38:34Z $ ++ * $Id: bcmdefs.h 316830 2012-02-23 20:29:22Z $ + */ + + #ifndef _bcmdefs_h_ +@@ -65,22 +65,9 @@ + #define BCMNMIATTACHFN(_fn) _fn + #define BCMNMIATTACHDATA(_data) _data + #define CONST const +- +-/* Do not put BCM47XX and __ARM_ARCH_7A__ to the same line. +- * DHD build has problem because the BCM47XX will be excluded in DHD release. +- */ +-#undef BCM47XX_CA9 +-#ifdef __ARM_ARCH_7A__ +-#define BCM47XX_CA9 +-#endif /* __ARM_ARCH_7A__ */ + #ifndef BCMFASTPATH +-#if defined(BCM47XX_CA9) +-#define BCMFASTPATH __attribute__ ((__section__ (".text.fastpath"))) +-#define BCMFASTPATH_HOST __attribute__ ((__section__ (".text.fastpath_host"))) +-#else + #define BCMFASTPATH + #define BCMFASTPATH_HOST +-#endif + #endif /* BCMFASTPATH */ + + +@@ -206,13 +193,9 @@ typedef struct { + + #if defined(BCM_RPC_NOCOPY) || defined(BCM_RCP_TXNOCOPY) + /* add 40 bytes to allow for extra RPC header and info */ +-#define BCMEXTRAHDROOM 260 ++#define BCMEXTRAHDROOM 220 + #else /* BCM_RPC_NOCOPY || BCM_RPC_TXNOCOPY */ +-#if defined(BCM47XX_CA9) +-#define BCMEXTRAHDROOM 224 +-#else +-#define BCMEXTRAHDROOM 204 +-#endif /* linux && BCM47XX_CA9 */ ++#define BCMEXTRAHDROOM 172 + #endif /* BCM_RPC_NOCOPY || BCM_RPC_TXNOCOPY */ + + /* Packet alignment for most efficient SDIO (can change based on platform) */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/bcmdevs.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcmdevs.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/bcmdevs.h 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcmdevs.h 2014-02-15 00:43:44.794014114 +0100 +@@ -1,7 +1,7 @@ + /* + * Broadcom device-specific manifest constants. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -21,7 +21,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: bcmdevs.h 414368 2013-07-24 15:00:23Z $ ++ * $Id: bcmdevs.h 329854 2012-04-27 01:42:28Z $ + */ + + #ifndef _BCMDEVS_H +@@ -63,12 +63,6 @@ + #define BCM_DNGL_BL_PID_43239 0xbd1b + #define BCM_DNGL_BL_PID_4324 0xbd1c + #define BCM_DNGL_BL_PID_4360 0xbd1d +-#define BCM_DNGL_BL_PID_43143 0xbd1e +-#define BCM_DNGL_BL_PID_43242 0xbd1f +-#define BCM_DNGL_BL_PID_43342 0xbd21 +-#define BCM_DNGL_BL_PID_4335 0xbd20 +-#define BCM_DNGL_BL_PID_4350 0xbd23 +-#define BCM_DNGL_BL_PID_43341 0xbd22 + + #define BCM_DNGL_BDC_PID 0x0bdc + #define BCM_DNGL_JTAG_PID 0x4a44 +@@ -137,8 +131,6 @@ + #define BCM4330_D11N5G_ID 0x4362 /* 4330 802.11n 5G device */ + #define BCM4336_D11N_ID 0x4343 /* 4336 802.11n 2.4GHz device */ + #define BCM6362_D11N_ID 0x435f /* 6362 802.11n dualband device */ +-#define BCM6362_D11N2G_ID 0x433f /* 6362 802.11n 2.4Ghz band id */ +-#define BCM6362_D11N5G_ID 0x434f /* 6362 802.11n 5Ghz band id */ + #define BCM4331_D11N_ID 0x4331 /* 4331 802.11n dualband id */ + #define BCM4331_D11N2G_ID 0x4332 /* 4331 802.11n 2.4Ghz band id */ + #define BCM4331_D11N5G_ID 0x4333 /* 4331 802.11n 5Ghz band id */ +@@ -154,42 +146,28 @@ + #define BCM43131_D11N2G_ID 0x43aa /* 43131 802.11n 2.4GHz device */ + #define BCM4314_D11N2G_ID 0x4364 /* 4314 802.11n 2.4G device */ + #define BCM43142_D11N2G_ID 0x4365 /* 43142 802.11n 2.4G device */ +-#define BCM43143_D11N2G_ID 0x4366 /* 43143 802.11n 2.4G device */ + #define BCM4334_D11N_ID 0x4380 /* 4334 802.11n dualband device */ + #define BCM4334_D11N2G_ID 0x4381 /* 4334 802.11n 2.4G device */ + #define BCM4334_D11N5G_ID 0x4382 /* 4334 802.11n 5G device */ +-#define BCM43342_D11N_ID 0x4383 /* 43342 802.11n dualband device */ +-#define BCM43342_D11N2G_ID 0x4384 /* 43342 802.11n 2.4G device */ +-#define BCM43342_D11N5G_ID 0x4385 /* 43342 802.11n 5G device */ + #define BCM43341_D11N_ID 0x4386 /* 43341 802.11n dualband device */ + #define BCM43341_D11N2G_ID 0x4387 /* 43341 802.11n 2.4G device */ + #define BCM43341_D11N5G_ID 0x4388 /* 43341 802.11n 5G device */ + #define BCM4360_D11AC_ID 0x43a0 + #define BCM4360_D11AC2G_ID 0x43a1 + #define BCM4360_D11AC5G_ID 0x43a2 +-#define BCM4335_D11AC_ID 0x43ae +-#define BCM4335_D11AC2G_ID 0x43af +-#define BCM4335_D11AC5G_ID 0x43b0 +-#define BCM4352_D11AC_ID 0x43b1 /* 4352 802.11ac dualband device */ +-#define BCM4352_D11AC2G_ID 0x43b2 /* 4352 802.11ac 2.4G device */ +-#define BCM4352_D11AC5G_ID 0x43b3 /* 4352 802.11ac 5G device */ + + /* PCI Subsystem ID */ + #define BCM943228HMB_SSID_VEN1 0x0607 + #define BCM94313HMGBL_SSID_VEN1 0x0608 + #define BCM94313HMG_SSID_VEN1 0x0609 +-#define BCM943142HM_SSID_VEN1 0x0611 +- +-#define BCM43143_D11N2G_ID 0x4366 /* 43143 802.11n 2.4G device */ +- +-#define BCM43242_D11N_ID 0x4367 /* 43242 802.11n dualband device */ +-#define BCM43242_D11N2G_ID 0x4368 /* 43242 802.11n 2.4G device */ +-#define BCM43242_D11N5G_ID 0x4369 /* 43242 802.11n 5G device */ + +-#define BCM4350_D11AC_ID 0x43a3 +-#define BCM4350_D11AC2G_ID 0x43a4 +-#define BCM4350_D11AC5G_ID 0x43a5 + ++#define BCM4335_D11AC_ID 0x43ae ++#define BCM4335_D11AC2G_ID 0x43af ++#define BCM4335_D11AC5G_ID 0x43b0 ++#define BCM4352_D11AC_ID 0x43b1 /* 4352 802.11ac dualband device */ ++#define BCM4352_D11AC2G_ID 0x43b2 /* 4352 802.11ac 2.4G device */ ++#define BCM4352_D11AC5G_ID 0x43b3 /* 4352 802.11ac 5G device */ + + #define BCMGPRS_UART_ID 0x4333 /* Uart id used by 4306/gprs card */ + #define BCMGPRS2_UART_ID 0x4344 /* Uart id used by 4306/gprs card */ +@@ -227,8 +205,6 @@ + #define BCM47XX_GIGETH_ID 0x471f /* 47xx GbE (5700) */ + #define BCM4712_MIPS_ID 0x4720 /* 4712 base devid */ + #define BCM4716_DEVICE_ID 0x4722 /* 4716 base devid */ +-#define BCM47XX_USB30H_ID 0x472a /* 47xx usb 3.0 host */ +-#define BCM47XX_USB30D_ID 0x472b /* 47xx usb 3.0 device */ + #define BCM47XX_SMBUS_EMU_ID 0x47fe /* 47xx emulated SMBus device */ + #define BCM47XX_XOR_EMU_ID 0x47ff /* 47xx emulated XOR engine */ + #define EPI41210_DEVICE_ID 0xa0fa /* bcm4210 */ +@@ -284,28 +260,21 @@ + #define BCM6362_CHIP_ID 0x6362 /* 6362 chipcommon chipid */ + #define BCM4314_CHIP_ID 0x4314 /* 4314 chipcommon chipid */ + #define BCM43142_CHIP_ID 43142 /* 43142 chipcommon chipid */ +-#define BCM43143_CHIP_ID 43143 /* 43143 chipcommon chipid */ + #define BCM4324_CHIP_ID 0x4324 /* 4324 chipcommon chipid */ + #define BCM43242_CHIP_ID 43242 /* 43242 chipcommon chipid */ +-#define BCM43243_CHIP_ID 43243 /* 43243 chipcommon chipid */ + #define BCM4334_CHIP_ID 0x4334 /* 4334 chipcommon chipid */ +-#define BCM4335_CHIP_ID 0x4335 /* 4335 chipcommon chipid */ +-#define BCM4339_CHIP_ID 0x4339 /* 4339 chipcommon chipid */ + #define BCM4360_CHIP_ID 0x4360 /* 4360 chipcommon chipid */ + #define BCM4352_CHIP_ID 0x4352 /* 4352 chipcommon chipid */ + #define BCM43526_CHIP_ID 0xAA06 +-#define BCM43340_CHIP_ID 43340 /* 43340 chipcommon chipid */ + #define BCM43341_CHIP_ID 43341 /* 43341 chipcommon chipid */ + #define BCM43342_CHIP_ID 43342 /* 43342 chipcommon chipid */ +-#define BCM4350_CHIP_ID 0x4350 /* 4350 chipcommon chipid */ ++ ++#define BCM4335_CHIP_ID 0x4335 + + #define BCM4342_CHIP_ID 4342 /* 4342 chipcommon chipid (OTP, RBBU) */ + #define BCM4402_CHIP_ID 0x4402 /* 4402 chipid */ + #define BCM4704_CHIP_ID 0x4704 /* 4704 chipcommon chipid */ + #define BCM4706_CHIP_ID 0x5300 /* 4706 chipcommon chipid */ +-#define BCM4707_CHIP_ID 53010 /* 4707 chipcommon chipid */ +-#define BCM53018_CHIP_ID 53018 /* 53018 chipcommon chipid */ +-#define BCM4707_CHIP(chipid) (((chipid) == BCM4707_CHIP_ID) || ((chipid) == BCM53018_CHIP_ID)) + #define BCM4710_CHIP_ID 0x4710 /* 4710 chipid */ + #define BCM4712_CHIP_ID 0x4712 /* 4712 chipcommon chipid */ + #define BCM4716_CHIP_ID 0x4716 /* 4716 chipcommon chipid */ +@@ -367,38 +336,27 @@ + #define BCM4314SDIO_FPBGA_PKG_ID (8 | 4) /* 4314 FpBGA SDIO package id */ + #define BCM4314DEV_PKG_ID (8 | 6) /* 4314 Developement package id */ + +-#define BCM4707_PKG_ID 1 /* 4707 package id */ +-#define BCM4708_PKG_ID 2 /* 4708 package id */ +-#define BCM4709_PKG_ID 0 /* 4709 package id */ +- + #define PCIXX21_FLASHMEDIA0_ID 0x8033 /* TI PCI xx21 Standard Host Controller */ + #define PCIXX21_SDIOH0_ID 0x8034 /* TI PCI xx21 Standard Host Controller */ + +-#define BCM4335_WLCSP_PKG_ID (0x0) /* WLCSP Module/Mobile SDIO/HSIC. */ +-#define BCM4335_FCBGA_PKG_ID (0x1) /* FCBGA PC/Embeded/Media PCIE/SDIO */ +-#define BCM4335_WLBGA_PKG_ID (0x2) /* WLBGA COB/Mobile SDIO/HSIC. */ +-#define BCM4335_FCBGAD_PKG_ID (0x3) /* FCBGA Debug Debug/Dev All if's. */ +-#define BCM4335_PKG_MASK (0x3) +- + /* boardflags */ + #define BFL_BTC2WIRE 0x00000001 /* old 2wire Bluetooth coexistence, OBSOLETE */ + #define BFL_BTCOEX 0x00000001 /* Board supports BTCOEX */ + #define BFL_PACTRL 0x00000002 /* Board has gpio 9 controlling the PA */ + #define BFL_AIRLINEMODE 0x00000004 /* Board implements gpio 13 radio disable indication, UNUSED */ + #define BFL_ADCDIV 0x00000008 /* Board has the rssi ADC divider */ +-#define BFL_DIS_256QAM 0x00000008 ++#define BFL_RFPLL 0x00000008 /* ACPHY: Changing RFPLL BW to be 150 MHz */ + #define BFL_ENETROBO 0x00000010 /* Board has robo switch or core */ + #define BFL_NOPLLDOWN 0x00000020 /* Not ok to power down the chip pll and oscillator */ + #define BFL_CCKHIPWR 0x00000040 /* Can do high-power CCK transmission */ + #define BFL_ENETADM 0x00000080 /* Board has ADMtek switch */ + #define BFL_ENETVLAN 0x00000100 /* Board has VLAN capability */ +-#define BFL_LTECOEX 0x00000200 /* Board has LTE coex capability */ ++#define BFL_UNUSED 0x00000200 + #define BFL_NOPCI 0x00000400 /* Board leaves PCI floating */ + #define BFL_FEM 0x00000800 /* Board supports the Front End Module */ + #define BFL_EXTLNA 0x00001000 /* Board has an external LNA in 2.4GHz band */ + #define BFL_HGPA 0x00002000 /* Board has a high gain PA */ +-#define BFL_BTC2WIRE_ALTGPIO 0x00004000 +-/* Board's BTC 2wire is in the alternate gpios OBSLETE */ ++#define BFL_BTC2WIRE_ALTGPIO 0x00004000 /* Board's BTC 2wire is in the alternate gpios */ + #define BFL_ALTIQ 0x00008000 /* Alternate I/Q settings */ + #define BFL_NOPA 0x00010000 /* Board has no PA */ + #define BFL_RSSIINV 0x00020000 /* Board's RSSI uses positive slope(not TSSI) */ +@@ -407,7 +365,6 @@ + #define BFL_PHASESHIFT 0x00100000 /* Board can support phase shifter */ + #define BFL_BUCKBOOST 0x00200000 /* Power topology uses BUCKBOOST */ + #define BFL_FEM_BT 0x00400000 /* Board has FEM and switch to share antenna w/ BT */ +-#define BFL_RXCHAIN_OFF_BT 0x00400000 /* one rxchain is to be shut off when BT is active */ + #define BFL_NOCBUCK 0x00800000 /* Power topology doesn't use CBUCK */ + #define BFL_CCKFAVOREVM 0x01000000 /* Favor CCK EVM over spectral mask */ + #define BFL_PALDO 0x02000000 /* Power topology uses PALDO */ +@@ -416,7 +373,6 @@ + #define BFL_UCPWRCTL_MININDX 0x08000000 /* Enforce min power index to avoid FEM damage */ + #define BFL_EXTLNA_5GHz 0x10000000 /* Board has an external LNA in 5GHz band */ + #define BFL_TRSW_1by2 0x20000000 /* Board has 2 TRSW's in 1by2 designs */ +-#define BFL_GAINBOOSTA01 0x20000000 /* 5g Gainboost for core0 and core1 */ + #define BFL_LO_TRSW_R_5GHz 0x40000000 /* In 5G do not throw TRSW to T for clipLO gain */ + #define BFL_ELNA_GAINDEF 0x80000000 /* Backoff InitGain based on elna_2g/5g field + * when this flag is set +@@ -453,8 +409,7 @@ + #define BFL2_ANAPACTRL_2G 0x00100000 /* 2G ext PAs are controlled by analog PA ctrl lines */ + #define BFL2_ANAPACTRL_5G 0x00200000 /* 5G ext PAs are controlled by analog PA ctrl lines */ + #define BFL2_ELNACTRL_TRSW_2G 0x00400000 /* AZW4329: 2G gmode_elna_gain controls TR Switch */ +-#define BFL2_BT_SHARE_ANT0 0x00800000 /* WLAN/BT share antenna 0 */ +-#define BFL2_BT_SHARE_BM_BIT0 0x00800000 /* bit 0 of WLAN/BT shared core bitmap */ ++#define BFL2_BT_SHARE_ANT0 0x00800000 /* share core0 antenna with BT */ + #define BFL2_TEMPSENSE_HIGHER 0x01000000 /* The tempsense threshold can sustain higher value + * than programmed. The exact delta is decided by + * driver per chip/boardtype. This can be used +@@ -466,46 +421,7 @@ + /* ucode control of eLNA during Tx */ + #define BFL2_4313_RADIOREG 0x10000000 + /* board rework */ +-#define BFL2_DYNAMIC_VMID 0x10000000 /* boardflag to enable dynamic Vmid idle TSSI CAL */ +-#define BFL2_SDR_EN 0x20000000 /* SDR enabled or disabled */ +-#define BFL2_LNA1BYPFORTR2G 0x40000000 /* acphy, enable lna1 bypass for clip gain, 2g */ +-#define BFL2_LNA1BYPFORTR5G 0x80000000 /* acphy, enable lna1 bypass for clip gain, 5g */ +- +-/* SROM 11 - 11ac boardflag definitions */ +-#define BFL_SROM11_BTCOEX 0x00000001 /* Board supports BTCOEX */ +-#define BFL_SROM11_WLAN_BT_SH_XTL 0x00000002 /* bluetooth and wlan share same crystal */ +-#define BFL_SROM11_EXTLNA 0x00001000 /* Board has an external LNA in 2.4GHz band */ +-#define BFL_SROM11_EXTLNA_5GHz 0x10000000 /* Board has an external LNA in 5GHz band */ +-#define BFL_SROM11_GAINBOOSTA01 0x20000000 /* 5g Gainboost for core0 and core1 */ +-#define BFL2_SROM11_APLL_WAR 0x00000002 /* Flag to implement alternative A-band PLL settings */ +-#define BFL2_SROM11_ANAPACTRL_2G 0x00100000 /* 2G ext PAs are ctrl-ed by analog PA ctrl lines */ +-#define BFL2_SROM11_ANAPACTRL_5G 0x00200000 /* 5G ext PAs are ctrl-ed by analog PA ctrl lines */ +- +-/* boardflags3 */ +-#define BFL3_FEMCTRL_SUB 0x00000007 /* acphy, subrevs of femctrl on top of srom_femctrl */ +-#define BFL3_RCAL_WAR 0x00000008 /* acphy, rcal war active on this board (4335a0) */ +-#define BFL3_TXGAINTBLID 0x00000070 /* acphy, txgain table id */ +-#define BFL3_TXGAINTBLID_SHIFT 0x4 /* acphy, txgain table id shift bit */ +-#define BFL3_TSSI_DIV_WAR 0x00000080 /* acphy, Seperate paparam for 20/40/80 */ +-#define BFL3_TSSI_DIV_WAR_SHIFT 0x7 /* acphy, Seperate paparam for 20/40/80 shift bit */ +-#define BFL3_FEMTBL_FROM_NVRAM 0x00000100 /* acphy, femctrl table is read from nvram */ +-#define BFL3_FEMTBL_FROM_NVRAM_SHIFT 0x8 /* acphy, femctrl table is read from nvram */ +-#define BFL3_AGC_CFG_2G 0x00000200 /* acphy, gain control configuration for 2G */ +-#define BFL3_AGC_CFG_5G 0x00000400 /* acphy, gain control configuration for 5G */ +-#define BFL3_PPR_BIT_EXT 0x00000800 /* acphy, bit position for 1bit extension for ppr */ +-#define BFL3_PPR_BIT_EXT_SHIFT 11 /* acphy, bit shift for 1bit extension for ppr */ +-#define BFL3_BBPLL_SPR_MODE_DIS 0x00001000 /* acphy, disables bbpll spur modes */ +-#define BFL3_RCAL_OTP_VAL_EN 0x00002000 /* acphy, to read rcal_trim value from otp */ +-#define BFL3_2GTXGAINTBL_BLANK 0x00004000 /* acphy, blank the first X ticks of 2g gaintbl */ +-#define BFL3_2GTXGAINTBL_BLANK_SHIFT 14 /* acphy, blank the first X ticks of 2g gaintbl */ +-#define BFL3_5GTXGAINTBL_BLANK 0x00008000 /* acphy, blank the first X ticks of 5g gaintbl */ +-#define BFL3_5GTXGAINTBL_BLANK_SHIFT 15 /* acphy, blank the first X ticks of 5g gaintbl */ +-#define BFL3_BT_SHARE_BM_BIT1 0x40000000 /* bit 1 of WLAN/BT shared core bitmap */ +-#define BFL3_PHASETRACK_MAX_ALPHABETA 0x00010000 /* acphy, to max out alpha,beta to 511 */ +-#define BFL3_PHASETRACK_MAX_ALPHABETA_SHIFT 16 /* acphy, to max out alpha,beta to 511 */ +-#define BFL3_BT_SHARE_BM_BIT1 0x40000000 /* bit 1 of WLAN/BT shared core bitmap */ +-#define BFL3_EN_NONBRCM_TXBF 0x10000000 /* acphy, enable non-brcm TXBF */ +-#define BFL3_EN_P2PLINK_TXBF 0x20000000 /* acphy, enable TXBF in p2p links */ ++#define BFL2_SDR_EN 0x20000000 /* SDR enabled or disabled */ + + /* board specific GPIO assignment, gpio 0-3 are also customer-configurable led */ + #define BOARD_GPIO_BTC3W_IN 0x850 /* bit 4 is RF_ACTIVE, bit 6 is STATUS, bit 11 is PRI */ +@@ -548,9 +464,6 @@ + /* 43341 Boards */ + #define BCM943341WLABGS_SSID 0x062d + +-/* 43342 Boards */ +-#define BCM943342FCAGBI_SSID 0x0641 +- + /* # of GPIO pins */ + #define GPIO_NUMPINS 32 + +@@ -565,18 +478,8 @@ + #define RDL_RAM_BASE_4328 0x80000000 + #define RDL_RAM_SIZE_4322 0x60000 + #define RDL_RAM_BASE_4322 0x60000000 +-#define RDL_RAM_SIZE_4360 0xA0000 +-#define RDL_RAM_BASE_4360 0x60000000 +-#define RDL_RAM_SIZE_43242 0x90000 +-#define RDL_RAM_BASE_43242 0x60000000 +-#define RDL_RAM_SIZE_43143 0x70000 +-#define RDL_RAM_BASE_43143 0x60000000 +-#define RDL_RAM_SIZE_4350 0xC0000 +-#define RDL_RAM_BASE_4350 0x180800 +- +-/* generic defs for nvram "muxenab" bits +-* Note: these differ for 4335a0. refer bcmchipc.h for specific mux options. +-*/ ++ ++/* generic defs for nvram "muxenab" bits */ + #define MUXENAB_UART 0x00000001 + #define MUXENAB_GPIO 0x00000002 + #define MUXENAB_ERCX 0x00000004 /* External Radio BT coex */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/bcmendian.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcmendian.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/bcmendian.h 2014-01-27 01:30:30.101433269 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcmendian.h 2014-02-15 00:43:44.793014092 +0100 +@@ -1,7 +1,7 @@ + /* + * Byte order utilities + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/bcm_mpool_pub.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcm_mpool_pub.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/bcm_mpool_pub.h 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcm_mpool_pub.h 2014-02-15 00:43:44.795014136 +0100 +@@ -35,7 +35,7 @@ + * and instrumentation on top of the heap, without modifying the heap + * allocation implementation. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/bcmpcispi.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcmpcispi.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/bcmpcispi.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcmpcispi.h 2014-02-15 00:43:44.793014092 +0100 +@@ -0,0 +1,181 @@ ++/* ++ * Broadcom PCI-SPI Host Controller Register Definitions ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: bcmpcispi.h 241182 2011-02-17 21:50:03Z $ ++ */ ++#ifndef _BCM_PCI_SPI_H ++#define _BCM_PCI_SPI_H ++ ++/* cpp contortions to concatenate w/arg prescan */ ++#ifndef PAD ++#define _PADLINE(line) pad ## line ++#define _XSTR(line) _PADLINE(line) ++#define PAD _XSTR(__LINE__) ++#endif /* PAD */ ++ ++ ++typedef volatile struct { ++ uint32 spih_ctrl; /* 0x00 SPI Control Register */ ++ uint32 spih_stat; /* 0x04 SPI Status Register */ ++ uint32 spih_data; /* 0x08 SPI Data Register, 32-bits wide */ ++ uint32 spih_ext; /* 0x0C SPI Extension Register */ ++ uint32 PAD[4]; /* 0x10-0x1F PADDING */ ++ ++ uint32 spih_gpio_ctrl; /* 0x20 SPI GPIO Control Register */ ++ uint32 spih_gpio_data; /* 0x24 SPI GPIO Data Register */ ++ uint32 PAD[6]; /* 0x28-0x3F PADDING */ ++ ++ uint32 spih_int_edge; /* 0x40 SPI Interrupt Edge Register (0=Level, 1=Edge) */ ++ uint32 spih_int_pol; /* 0x44 SPI Interrupt Polarity Register (0=Active Low, */ ++ /* 1=Active High) */ ++ uint32 spih_int_mask; /* 0x48 SPI Interrupt Mask */ ++ uint32 spih_int_status; /* 0x4C SPI Interrupt Status */ ++ uint32 PAD[4]; /* 0x50-0x5F PADDING */ ++ ++ uint32 spih_hex_disp; /* 0x60 SPI 4-digit hex display value */ ++ uint32 spih_current_ma; /* 0x64 SPI SD card current consumption in mA */ ++ uint32 PAD[1]; /* 0x68 PADDING */ ++ uint32 spih_disp_sel; /* 0x6c SPI 4-digit hex display mode select (1=current) */ ++ uint32 PAD[4]; /* 0x70-0x7F PADDING */ ++ uint32 PAD[8]; /* 0x80-0x9F PADDING */ ++ uint32 PAD[8]; /* 0xA0-0xBF PADDING */ ++ uint32 spih_pll_ctrl; /* 0xC0 PLL Control Register */ ++ uint32 spih_pll_status; /* 0xC4 PLL Status Register */ ++ uint32 spih_xtal_freq; /* 0xC8 External Clock Frequency in units of 10000Hz */ ++ uint32 spih_clk_count; /* 0xCC External Clock Count Register */ ++ ++} spih_regs_t; ++ ++typedef volatile struct { ++ uint32 cfg_space[0x40]; /* 0x000-0x0FF PCI Configuration Space (Read Only) */ ++ uint32 P_IMG_CTRL0; /* 0x100 PCI Image0 Control Register */ ++ ++ uint32 P_BA0; /* 0x104 32 R/W PCI Image0 Base Address register */ ++ uint32 P_AM0; /* 0x108 32 R/W PCI Image0 Address Mask register */ ++ uint32 P_TA0; /* 0x10C 32 R/W PCI Image0 Translation Address register */ ++ uint32 P_IMG_CTRL1; /* 0x110 32 R/W PCI Image1 Control register */ ++ uint32 P_BA1; /* 0x114 32 R/W PCI Image1 Base Address register */ ++ uint32 P_AM1; /* 0x118 32 R/W PCI Image1 Address Mask register */ ++ uint32 P_TA1; /* 0x11C 32 R/W PCI Image1 Translation Address register */ ++ uint32 P_IMG_CTRL2; /* 0x120 32 R/W PCI Image2 Control register */ ++ uint32 P_BA2; /* 0x124 32 R/W PCI Image2 Base Address register */ ++ uint32 P_AM2; /* 0x128 32 R/W PCI Image2 Address Mask register */ ++ uint32 P_TA2; /* 0x12C 32 R/W PCI Image2 Translation Address register */ ++ uint32 P_IMG_CTRL3; /* 0x130 32 R/W PCI Image3 Control register */ ++ uint32 P_BA3; /* 0x134 32 R/W PCI Image3 Base Address register */ ++ uint32 P_AM3; /* 0x138 32 R/W PCI Image3 Address Mask register */ ++ uint32 P_TA3; /* 0x13C 32 R/W PCI Image3 Translation Address register */ ++ uint32 P_IMG_CTRL4; /* 0x140 32 R/W PCI Image4 Control register */ ++ uint32 P_BA4; /* 0x144 32 R/W PCI Image4 Base Address register */ ++ uint32 P_AM4; /* 0x148 32 R/W PCI Image4 Address Mask register */ ++ uint32 P_TA4; /* 0x14C 32 R/W PCI Image4 Translation Address register */ ++ uint32 P_IMG_CTRL5; /* 0x150 32 R/W PCI Image5 Control register */ ++ uint32 P_BA5; /* 0x154 32 R/W PCI Image5 Base Address register */ ++ uint32 P_AM5; /* 0x158 32 R/W PCI Image5 Address Mask register */ ++ uint32 P_TA5; /* 0x15C 32 R/W PCI Image5 Translation Address register */ ++ uint32 P_ERR_CS; /* 0x160 32 R/W PCI Error Control and Status register */ ++ uint32 P_ERR_ADDR; /* 0x164 32 R PCI Erroneous Address register */ ++ uint32 P_ERR_DATA; /* 0x168 32 R PCI Erroneous Data register */ ++ ++ uint32 PAD[5]; /* 0x16C-0x17F PADDING */ ++ ++ uint32 WB_CONF_SPC_BAR; /* 0x180 32 R WISHBONE Configuration Space Base Address */ ++ uint32 W_IMG_CTRL1; /* 0x184 32 R/W WISHBONE Image1 Control register */ ++ uint32 W_BA1; /* 0x188 32 R/W WISHBONE Image1 Base Address register */ ++ uint32 W_AM1; /* 0x18C 32 R/W WISHBONE Image1 Address Mask register */ ++ uint32 W_TA1; /* 0x190 32 R/W WISHBONE Image1 Translation Address reg */ ++ uint32 W_IMG_CTRL2; /* 0x194 32 R/W WISHBONE Image2 Control register */ ++ uint32 W_BA2; /* 0x198 32 R/W WISHBONE Image2 Base Address register */ ++ uint32 W_AM2; /* 0x19C 32 R/W WISHBONE Image2 Address Mask register */ ++ uint32 W_TA2; /* 0x1A0 32 R/W WISHBONE Image2 Translation Address reg */ ++ uint32 W_IMG_CTRL3; /* 0x1A4 32 R/W WISHBONE Image3 Control register */ ++ uint32 W_BA3; /* 0x1A8 32 R/W WISHBONE Image3 Base Address register */ ++ uint32 W_AM3; /* 0x1AC 32 R/W WISHBONE Image3 Address Mask register */ ++ uint32 W_TA3; /* 0x1B0 32 R/W WISHBONE Image3 Translation Address reg */ ++ uint32 W_IMG_CTRL4; /* 0x1B4 32 R/W WISHBONE Image4 Control register */ ++ uint32 W_BA4; /* 0x1B8 32 R/W WISHBONE Image4 Base Address register */ ++ uint32 W_AM4; /* 0x1BC 32 R/W WISHBONE Image4 Address Mask register */ ++ uint32 W_TA4; /* 0x1C0 32 R/W WISHBONE Image4 Translation Address reg */ ++ uint32 W_IMG_CTRL5; /* 0x1C4 32 R/W WISHBONE Image5 Control register */ ++ uint32 W_BA5; /* 0x1C8 32 R/W WISHBONE Image5 Base Address register */ ++ uint32 W_AM5; /* 0x1CC 32 R/W WISHBONE Image5 Address Mask register */ ++ uint32 W_TA5; /* 0x1D0 32 R/W WISHBONE Image5 Translation Address reg */ ++ uint32 W_ERR_CS; /* 0x1D4 32 R/W WISHBONE Error Control and Status reg */ ++ uint32 W_ERR_ADDR; /* 0x1D8 32 R WISHBONE Erroneous Address register */ ++ uint32 W_ERR_DATA; /* 0x1DC 32 R WISHBONE Erroneous Data register */ ++ uint32 CNF_ADDR; /* 0x1E0 32 R/W Configuration Cycle register */ ++ uint32 CNF_DATA; /* 0x1E4 32 R/W Configuration Cycle Generation Data reg */ ++ ++ uint32 INT_ACK; /* 0x1E8 32 R Interrupt Acknowledge register */ ++ uint32 ICR; /* 0x1EC 32 R/W Interrupt Control register */ ++ uint32 ISR; /* 0x1F0 32 R/W Interrupt Status register */ ++} spih_pciregs_t; ++ ++/* ++ * PCI Core interrupt enable and status bit definitions. ++ */ ++ ++/* PCI Core ICR Register bit definitions */ ++#define PCI_INT_PROP_EN (1 << 0) /* Interrupt Propagation Enable */ ++#define PCI_WB_ERR_INT_EN (1 << 1) /* Wishbone Error Interrupt Enable */ ++#define PCI_PCI_ERR_INT_EN (1 << 2) /* PCI Error Interrupt Enable */ ++#define PCI_PAR_ERR_INT_EN (1 << 3) /* Parity Error Interrupt Enable */ ++#define PCI_SYS_ERR_INT_EN (1 << 4) /* System Error Interrupt Enable */ ++#define PCI_SOFTWARE_RESET (1U << 31) /* Software reset of the PCI Core. */ ++ ++ ++/* PCI Core ISR Register bit definitions */ ++#define PCI_INT_PROP_ST (1 << 0) /* Interrupt Propagation Status */ ++#define PCI_WB_ERR_INT_ST (1 << 1) /* Wishbone Error Interrupt Status */ ++#define PCI_PCI_ERR_INT_ST (1 << 2) /* PCI Error Interrupt Status */ ++#define PCI_PAR_ERR_INT_ST (1 << 3) /* Parity Error Interrupt Status */ ++#define PCI_SYS_ERR_INT_ST (1 << 4) /* System Error Interrupt Status */ ++ ++ ++/* Registers on the Wishbone bus */ ++#define SPIH_CTLR_INTR (1 << 0) /* SPI Host Controller Core Interrupt */ ++#define SPIH_DEV_INTR (1 << 1) /* SPI Device Interrupt */ ++#define SPIH_WFIFO_INTR (1 << 2) /* SPI Tx FIFO Empty Intr (FPGA Rev >= 8) */ ++ ++/* GPIO Bit definitions */ ++#define SPIH_CS (1 << 0) /* SPI Chip Select (active low) */ ++#define SPIH_SLOT_POWER (1 << 1) /* SD Card Slot Power Enable */ ++#define SPIH_CARD_DETECT (1 << 2) /* SD Card Detect */ ++ ++/* SPI Status Register Bit definitions */ ++#define SPIH_STATE_MASK 0x30 /* SPI Transfer State Machine state mask */ ++#define SPIH_STATE_SHIFT 4 /* SPI Transfer State Machine state shift */ ++#define SPIH_WFFULL (1 << 3) /* SPI Write FIFO Full */ ++#define SPIH_WFEMPTY (1 << 2) /* SPI Write FIFO Empty */ ++#define SPIH_RFFULL (1 << 1) /* SPI Read FIFO Full */ ++#define SPIH_RFEMPTY (1 << 0) /* SPI Read FIFO Empty */ ++ ++#define SPIH_EXT_CLK (1U << 31) /* Use External Clock as PLL Clock source. */ ++ ++#define SPIH_PLL_NO_CLK (1 << 1) /* Set to 1 if the PLL's input clock is lost. */ ++#define SPIH_PLL_LOCKED (1 << 3) /* Set to 1 when the PLL is locked. */ ++ ++/* Spin bit loop bound check */ ++#define SPI_SPIN_BOUND 0xf4240 /* 1 million */ ++ ++#endif /* _BCM_PCI_SPI_H */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/bcmperf.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcmperf.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/bcmperf.h 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcmperf.h 2014-02-15 00:43:44.794014114 +0100 +@@ -1,7 +1,7 @@ + /* + * Performance counters software interface. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/bcmsdbus.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcmsdbus.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/bcmsdbus.h 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcmsdbus.h 2014-02-15 00:43:44.794014114 +0100 +@@ -2,7 +2,7 @@ + * Definitions for API from sdio common code (bcmsdh) to individual + * host controller drivers. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -22,7 +22,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: bcmsdbus.h 408155 2013-06-17 21:52:27Z $ ++ * $Id: bcmsdbus.h 347614 2012-07-27 10:24:51Z $ + */ + + #ifndef _sdio_api_h_ +@@ -48,33 +48,13 @@ + + #ifdef BCMSDIOH_TXGLOM + /* Max number of glommed pkts */ +-#ifdef CUSTOM_MAX_TXGLOM_SIZE +-#define SDPCM_MAXGLOM_SIZE CUSTOM_MAX_TXGLOM_SIZE +-#else + #define SDPCM_MAXGLOM_SIZE 10 +-#endif /* CUSTOM_MAX_TXGLOM_SIZE */ ++#define SDPCM_DEFGLOM_SIZE 3 + + #define SDPCM_TXGLOM_CPY 0 /* SDIO 2.0 should use copy mode */ + #define SDPCM_TXGLOM_MDESC 1 /* SDIO 3.0 should use multi-desc mode */ +- +-#ifdef BCMSDIOH_TXGLOM_HIGHSPEED +-#define SDPCM_DEFGLOM_MODE SDPCM_TXGLOM_MDESC +-#ifdef CUSTOM_DEF_TXGLOM_SIZE +-#define SDPCM_DEFGLOM_SIZE CUSTOM_DEF_TXGLOM_SIZE +-#else +-#define SDPCM_DEFGLOM_SIZE 10 +-#endif /* CUSTOM_DEF_TXGLOM_SIZE */ +-#else +-#define SDPCM_DEFGLOM_MODE SDPCM_TXGLOM_CPY +-#define SDPCM_DEFGLOM_SIZE 3 +-#endif /* BCMSDIOH_TXGLOM_HIGHSPEED */ +- +-#if SDPCM_DEFGLOM_SIZE > SDPCM_MAXGLOM_SIZE +-#warning "SDPCM_DEFGLOM_SIZE cannot be higher than SDPCM_MAXGLOM_SIZE!!" +-#undef SDPCM_DEFGLOM_SIZE +-#define SDPCM_DEFGLOM_SIZE SDPCM_MAXGLOM_SIZE + #endif +-#endif /* BCMSDIOH_TXGLOM */ ++ + + typedef int SDIOH_API_RC; + +@@ -116,12 +96,12 @@ extern SDIOH_API_RC sdioh_request_buffer + void *pkt); + + #ifdef BCMSDIOH_TXGLOM +-extern void sdioh_glom_post(sdioh_info_t *sd, uint8 *frame, void *pkt, uint len); ++extern void sdioh_glom_post(sdioh_info_t *sd, uint8 *frame, uint len); + extern void sdioh_glom_clear(sdioh_info_t *sd); + extern uint sdioh_set_mode(sdioh_info_t *sd, uint mode); + extern bool sdioh_glom_enabled(void); + #else +-#define sdioh_glom_post(a, b, c, d) ++#define sdioh_glom_post(a, b, c) + #define sdioh_glom_clear(a) + #define sdioh_set_mode(a) (0) + #define sdioh_glom_enabled() (FALSE) +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/bcmsdh.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcmsdh.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/bcmsdh.h 2014-01-27 01:30:30.101433269 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcmsdh.h 2014-02-15 00:43:44.793014092 +0100 +@@ -3,7 +3,7 @@ + * export functions to client drivers + * abstract OS and BUS specific details of SDIO + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -23,7 +23,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: bcmsdh.h 414953 2013-07-26 17:36:27Z $ ++ * $Id: bcmsdh.h 347614 2012-07-27 10:24:51Z $ + */ + + /** +@@ -48,8 +48,6 @@ extern const uint bcmsdh_msglevel; + typedef struct bcmsdh_info bcmsdh_info_t; + typedef void (*bcmsdh_cb_fn_t)(void *); + +-extern struct device *pm_dev; +- + /* Attach and build an interface to the underlying SD host driver. + * - Allocates resources (structs, arrays, mem, OS handles, etc) needed by bcmsdh. + * - Returns the bcmsdh handle and virtual address base for register access. +@@ -57,7 +55,13 @@ extern struct device *pm_dev; + * implementation may maintain a single "default" handle (e.g. the first or + * most recent one) to enable single-instance implementations to pass NULL. + */ ++ ++#if 0 && (NDISVER >= 0x0630) && 1 ++extern bcmsdh_info_t *bcmsdh_attach(osl_t *osh, void *cfghdl, ++ void **regsva, uint irq, shared_info_t *sh); ++#else + extern bcmsdh_info_t *bcmsdh_attach(osl_t *osh, void *cfghdl, void **regsva, uint irq); ++#endif + + /* Detach - freeup resources allocated in attach */ + extern int bcmsdh_detach(osl_t *osh, void *sdh); +@@ -141,7 +145,7 @@ extern int bcmsdh_recv_buf(void *sdh, ui + uint8 *buf, uint nbytes, void *pkt, + bcmsdh_cmplt_fn_t complete_fn, void *handle); + +-extern void bcmsdh_glom_post(void *sdh, uint8 *frame, void *pkt, uint len); ++extern void bcmsdh_glom_post(void *sdh, uint8 *frame, uint len); + extern void bcmsdh_glom_clear(void *sdh); + extern uint bcmsdh_set_mode(void *sdh, uint mode); + extern bool bcmsdh_glom_enabled(void); +@@ -211,12 +215,16 @@ extern void bcmsdh_device_remove(void * + extern int bcmsdh_reg_sdio_notify(void* semaphore); + extern void bcmsdh_unreg_sdio_notify(void); + ++extern int bcmsdh_set_drvdata(void * dhdp); ++ + #if defined(OOB_INTR_ONLY) + extern int bcmsdh_register_oob_intr(void * dhdp); + extern void bcmsdh_unregister_oob_intr(void); + extern void bcmsdh_oob_intr_set(bool enable); +-extern bool bcmsdh_is_oob_intr_registered(void); +-#endif ++#endif ++#if defined(HW_OOB) ++void bcmsdh_config_hw_oob_intr(bcmsdh_info_t *sdh, uint chip); ++#endif + + /* Function to pass device-status bits to DHD. */ + extern uint32 bcmsdh_get_dstatus(void *sdh); +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h 2014-02-15 00:43:44.794014114 +0100 +@@ -1,7 +1,7 @@ + /* + * BCMSDH Function Driver for the native SDIO/MMC driver in the Linux Kernel + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -21,19 +21,21 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: bcmsdh_sdmmc.h 396592 2013-04-13 16:14:38Z $ ++ * $Id: bcmsdh_sdmmc.h 366812 2012-11-05 13:49:32Z $ + */ + + #ifndef __BCMSDH_SDMMC_H__ + #define __BCMSDH_SDMMC_H__ + +-#define sd_err(x) ++#define sd_err(x) printf x + #define sd_trace(x) + #define sd_info(x) + #define sd_debug(x) + #define sd_data(x) + #define sd_ctrl(x) + ++#define sd_trace_hw4 sd_trace ++ + #define sd_sync_dma(sd, read, nbytes) + #define sd_init_dma(sd) + #define sd_ack_intr(sd) +@@ -59,19 +61,10 @@ extern void sdioh_sdmmc_osfree(sdioh_inf + + /* private bus modes */ + #define SDIOH_MODE_SD4 2 +-#define CLIENT_INTR 0x100 /* Get rid of this! */ +- +-#ifdef BCMSDIOH_TXGLOM +- +-typedef struct glom_buf { +- void *glom_pkt_head; +- void *glom_pkt_tail; +- uint32 count; /* Total number of pkts queued */ +-} glom_buf_t; +-#endif /* BCMSDIOH_TXGLOM */ ++#define CLIENT_INTR 0x100 /* Get rid of this! */ + + struct sdioh_info { +- osl_t *osh; /* osh handler */ ++ osl_t *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 */ +@@ -79,27 +72,22 @@ struct sdioh_info { + uint16 intmask; /* Current active interrupts */ + void *sdos_info; /* Pointer to per-OS private data */ + +- uint irq; /* Client irq */ +- int intrcount; /* Client interrupts */ ++ 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. */ ++ 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 */ + uint8 num_funcs; /* Supported funcs on client */ + uint32 com_cis_ptr; +- uint32 func_cis_ptr[SDIOD_MAX_IOFUNCS]; ++ uint32 func_cis_ptr[SDIOD_MAX_IOFUNCS]; + + #define SDIOH_SDMMC_MAX_SG_ENTRIES 32 + struct scatterlist sg_list[SDIOH_SDMMC_MAX_SG_ENTRIES]; + bool use_rxchain; +- +-#ifdef BCMSDIOH_TXGLOM +- glom_buf_t glom_info; /* pkt information used for glomming */ +- uint txglom_mode; /* Txglom mode: 0 - copy, 1 - multi-descriptor */ +-#endif + }; + + /************************************************************ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/bcmsdpcm.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcmsdpcm.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/bcmsdpcm.h 2014-01-27 01:30:30.101433269 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcmsdpcm.h 2014-02-15 00:43:44.793014092 +0100 +@@ -2,7 +2,7 @@ + * Broadcom SDIO/PCMCIA + * Software-specific definitions shared between device and host side + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -22,7 +22,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: bcmsdpcm.h 364353 2012-10-23 20:31:46Z $ ++ * $Id: bcmsdpcm.h 362722 2012-10-12 23:55:55Z $ + */ + + #ifndef _bcmsdpcm_h_ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/bcmsdspi.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcmsdspi.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/bcmsdspi.h 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcmsdspi.h 2014-02-15 00:43:44.794014114 +0100 +@@ -1,7 +1,7 @@ + /* + * SD-SPI Protocol Conversion - BCMSDH->SPI Translation Layer + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/bcmsdstd.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcmsdstd.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/bcmsdstd.h 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcmsdstd.h 2014-02-15 00:43:44.794014114 +0100 +@@ -1,7 +1,7 @@ + /* + * 'Standard' SDIO HOST CONTROLLER driver + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -21,7 +21,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: bcmsdstd.h 343301 2012-07-06 13:07:32Z $ ++ * $Id: bcmsdstd.h 347614 2012-07-27 10:24:51Z $ + */ + #ifndef _BCM_SD_STD_H + #define _BCM_SD_STD_H +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/bcmspi.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcmspi.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/bcmspi.h 2014-01-27 01:30:30.101433269 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcmspi.h 2014-02-15 00:43:44.793014092 +0100 +@@ -1,7 +1,7 @@ + /* + * Broadcom SPI Low-Level Hardware Driver API + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/bcmutils.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcmutils.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/bcmutils.h 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcmutils.h 2014-02-15 00:43:44.794014114 +0100 +@@ -1,7 +1,7 @@ + /* + * Misc useful os-independent macros and functions. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -21,7 +21,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: bcmutils.h 412804 2013-07-16 16:26:39Z $ ++ * $Id: bcmutils.h 354837 2012-09-04 06:58:44Z $ + */ + + #ifndef _bcmutils_h_ +@@ -140,8 +140,6 @@ typedef struct { + increases with use ('inverse' of max_avail) + */ + uint32 queue_capacity; /* the maximum capacity of the queue */ +- uint32 rtsfail; /* count of rts attempts that failed to receive cts */ +- uint32 acked; /* count of packets sent (acked) successfully */ + } pktq_counters_t; + #endif /* PKTQ_LOG */ + +@@ -158,9 +156,7 @@ struct pktq { + /* q array must be last since # of elements can be either PKTQ_MAX_PREC or 1 */ + struct pktq_prec q[PKTQ_MAX_PREC]; + #ifdef PKTQ_LOG +- pktq_counters_t _prec_cnt[PKTQ_MAX_PREC]; /* Counters per queue */ +- pktq_counters_t _prec_bytes[PKTQ_MAX_PREC]; /* Byte count per queue */ +- uint32 _logtime; /* timestamp of last counter clear */ ++ pktq_counters_t _prec_cnt[PKTQ_MAX_PREC]; /* Counters per queue */ + #endif + }; + +@@ -304,7 +300,6 @@ extern void *pktq_penq(struct pktq *pq, + extern void *pktq_penq_head(struct pktq *pq, int prec, void *p); + extern void *pktq_pdeq(struct pktq *pq, int prec); + extern void *pktq_pdeq_prev(struct pktq *pq, int prec, void *prev_p); +-extern void *pktq_pdeq_with_fn(struct pktq *pq, int prec, ifpkt_cb_t fn, int arg); + extern void *pktq_pdeq_tail(struct pktq *pq, int prec); + /* Empty the queue at particular precedence level */ + extern void pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir, +@@ -351,8 +346,7 @@ extern uint pkttotlen(osl_t *osh, void * + extern void *pktlast(osl_t *osh, void *p); + extern uint pktsegcnt(osl_t *osh, void *p); + extern uint pktsegcnt_war(osl_t *osh, void *p); +-extern uint8 *pktdataoffset(osl_t *osh, void *p, uint offset); +-extern void *pktoffset(osl_t *osh, void *p, uint offset); ++extern uint8 *pktoffset(osl_t *osh, void *p, uint offset); + + /* Get priority from a packet and pass it back in scb (or equiv) */ + #define PKTPRIO_VDSCP 0x100 /* DSCP prio found after VLAN tag */ +@@ -360,22 +354,6 @@ extern void *pktoffset(osl_t *osh, void + #define PKTPRIO_UPD 0x400 /* DSCP used to update VLAN prio */ + #define PKTPRIO_DSCP 0x800 /* DSCP prio found */ + +-/* DSCP type definitions (RFC4594) */ +-/* AF1x: High-Throughput Data (RFC2597) */ +-#define DSCP_AF11 0x0A +-#define DSCP_AF12 0x0C +-#define DSCP_AF13 0x0E +-/* AF2x: Low-Latency Data (RFC2597) */ +-#define DSCP_AF21 0x12 +-#define DSCP_AF22 0x14 +-#define DSCP_AF23 0x16 +-/* AF3x: Multimedia Streaming (RFC2597) */ +-#define DSCP_AF31 0x1A +-#define DSCP_AF32 0x1C +-#define DSCP_AF33 0x1E +-/* EF: Telephony (RFC3246) */ +-#define DSCP_EF 0x2E +- + extern uint pktsetprio(void *pkt, bool update_vtag); + + /* string */ +@@ -551,11 +529,7 @@ extern int bcm_format_ssid(char* buf, co + #define BCME_NODEVICE -40 /* Device not present */ + #define BCME_NMODE_DISABLED -41 /* NMODE disabled */ + #define BCME_NONRESIDENT -42 /* access to nonresident overlay */ +-#define BCME_SCANREJECT -43 /* reject scan request */ +-#define BCME_USAGE_ERROR -44 /* WLCMD usage error */ +-#define BCME_IOCTL_ERROR -45 /* WLCMD ioctl error */ +-#define BCME_SERIAL_PORT_ERR -46 /* RWL serial port error */ +-#define BCME_LAST BCME_SERIAL_PORT_ERR ++#define BCME_LAST BCME_NONRESIDENT + + /* These are collection of BCME Error strings */ + #define BCMERRSTRINGTABLE { \ +@@ -602,10 +576,6 @@ extern int bcm_format_ssid(char* buf, co + "Device Not Present", \ + "NMODE Disabled", \ + "Nonresident overlay access", \ +- "Scan Rejected", \ +- "WLCMD usage error", \ +- "WLCMD ioctl error", \ +- "RWL serial port error", \ + } + + #ifndef ABS +@@ -620,24 +590,6 @@ extern int bcm_format_ssid(char* buf, co + #define MAX(a, b) (((a) > (b)) ? (a) : (b)) + #endif /* MAX */ + +-/* limit to [min, max] */ +-#ifndef LIMIT_TO_RANGE +-#define LIMIT_TO_RANGE(x, min, max) \ +- ((x) < (min) ? (min) : ((x) > (max) ? (max) : (x))) +-#endif /* LIMIT_TO_RANGE */ +- +-/* limit to max */ +-#ifndef LIMIT_TO_MAX +-#define LIMIT_TO_MAX(x, max) \ +- (((x) > (max) ? (max) : (x))) +-#endif /* LIMIT_TO_MAX */ +- +-/* limit to min */ +-#ifndef LIMIT_TO_MIN +-#define LIMIT_TO_MIN(x, min) \ +- (((x) < (min) ? (min) : (x))) +-#endif /* LIMIT_TO_MIN */ +- + #define CEIL(x, y) (((x) + ((y) - 1)) / (y)) + #define ROUNDUP(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) + #define ISALIGNED(a, x) (((uintptr)(a) & ((x) - 1)) == 0) +@@ -666,10 +618,6 @@ extern int bcm_format_ssid(char* buf, co + #define ARRAYSIZE(a) (sizeof(a) / sizeof(a[0])) + #endif + +-#ifndef ARRAYLAST /* returns pointer to last array element */ +-#define ARRAYLAST(a) (&a[ARRAYSIZE(a)-1]) +-#endif +- + /* Reference a function; used to prevent a static function from being optimized out */ + extern void *_bcmutils_dummy_fn; + #define REFERENCE_FUNCTION(f) (_bcmutils_dummy_fn = (void *)(f)) +@@ -679,21 +627,12 @@ extern void *_bcmutils_dummy_fn; + #ifndef NBBY /* the BSD family defines NBBY */ + #define NBBY 8 /* 8 bits per byte */ + #endif /* #ifndef NBBY */ +-#ifdef BCMUTILS_BIT_MACROS_USE_FUNCS +-extern void setbit(void *array, uint bit); +-extern void clrbit(void *array, uint bit); +-extern bool isset(const void *array, uint bit); +-extern bool isclr(const void *array, uint bit); +-#else + #define setbit(a, i) (((uint8 *)a)[(i) / NBBY] |= 1 << ((i) % NBBY)) + #define clrbit(a, i) (((uint8 *)a)[(i) / NBBY] &= ~(1 << ((i) % NBBY))) + #define isset(a, i) (((const uint8 *)a)[(i) / NBBY] & (1 << ((i) % NBBY))) + #define isclr(a, i) ((((const uint8 *)a)[(i) / NBBY] & (1 << ((i) % NBBY))) == 0) +-#endif + #endif /* setbit */ + +-#define isbitset(a, i) (((a) & (1 << (i))) != 0) +- + #define NBITS(type) (sizeof(type) * 8) + #define NBITVAL(nbits) (1 << (nbits)) + #define MAXBITVAL(nbits) ((1 << (nbits)) - 1) +@@ -758,13 +697,6 @@ typedef struct bcm_bit_desc { + const char* name; + } bcm_bit_desc_t; + +-/* bcm_format_field */ +-typedef struct bcm_bit_desc_ex { +- uint32 mask; +- const bcm_bit_desc_t *bitfield; +-} bcm_bit_desc_ex_t; +- +- + /* tag_ID/length/value_buffer tuple */ + typedef struct bcm_tlv { + uint8 id; +@@ -811,9 +743,6 @@ extern uint32 hndcrc32(uint8 *p, uint nb + /* format/print */ + #if defined(DHD_DEBUG) || defined(WLMSG_PRHDRS) || defined(WLMSG_PRPKT) || \ + defined(WLMSG_ASSOC) +-/* print out the value a field has: fields may have 1-32 bits and may hold any value */ +-extern int bcm_format_field(const bcm_bit_desc_ex_t *bd, uint32 field, char* buf, int len); +-/* print out which bits in flags are set */ + extern int bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char* buf, int len); + #endif + +@@ -835,7 +764,7 @@ extern bcm_tlv_t *bcm_parse_ordered_tlvs + + /* bcmerror */ + extern const char *bcmerrorstr(int bcmerror); +-/* extern bcm_tlv_t *bcm_parse_tlvs(void *buf, int buflen, uint key); */ ++extern bcm_tlv_t *bcm_parse_tlvs(void *buf, int buflen, uint key); + + /* multi-bool data type: set of bools, mbool is true if any is set */ + typedef uint32 mbool; +@@ -871,13 +800,6 @@ extern uint8 bcm_mw_to_qdbm(uint16 mw); + extern uint bcm_mkiovar(char *name, char *data, uint datalen, char *buf, uint len); + + unsigned int process_nvram_vars(char *varbuf, unsigned int len); +-extern bcm_tlv_t *find_vendor_ie(void *tlvs, int tlvs_len, +- const char *voui, uint8 *type, int type_len); +- +-/* calculate a * b + c */ +-extern void bcm_uint64_multiple_add(uint32* r_high, uint32* r_low, uint32 a, uint32 b, uint32 c); +-/* calculate a / b */ +-extern void bcm_uint64_divide(uint32* r, uint32 a_high, uint32 a_low, uint32 b); + + #ifdef __cplusplus + } +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/bcmwifi_channels.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcmwifi_channels.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/bcmwifi_channels.h 2014-01-27 01:30:30.101433269 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcmwifi_channels.h 2014-02-15 00:43:44.793014092 +0100 +@@ -3,7 +3,7 @@ + * This header file housing the define and function prototype use by + * both the wl driver, tools & Apps. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -47,8 +47,7 @@ typedef uint16 chanspec_t; + * this is that + 1 rounded up to a multiple of NBBY (8). + * DO NOT MAKE it > 255: channels are uint8's all over + */ +-#define CHSPEC_CTLOVLP(sp1, sp2, sep) (ABS(wf_chspec_ctlchan(sp1) - wf_chspec_ctlchan(sp2)) < \ +- (sep)) ++#define CHSPEC_CTLOVLP(sp1, sp2, sep) ABS(wf_chspec_ctlchan(sp1) - wf_chspec_ctlchan(sp2)) < (sep) + + /* All builds use the new 11ac ratespec/chanspec */ + #undef D11AC_IOTYPES +@@ -87,13 +86,6 @@ typedef uint16 chanspec_t; + #define LOWER_20_SB(channel) (((channel) > CH_10MHZ_APART) ? ((channel) - CH_10MHZ_APART) : 0) + #define UPPER_20_SB(channel) (((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? \ + ((channel) + CH_10MHZ_APART) : 0) +- +-#define LL_20_SB(channel) (((channel) > 3 * CH_10MHZ_APART) ? ((channel) - 3 * CH_10MHZ_APART) : 0) +-#define UU_20_SB(channel) (((channel) < (MAXCHANNEL - 3 * CH_10MHZ_APART)) ? \ +- ((channel) + 3 * CH_10MHZ_APART) : 0) +-#define LU_20_SB(channel) LOWER_20_SB(channel) +-#define UL_20_SB(channel) UPPER_20_SB(channel) +- + #define CHSPEC_WLCBANDUNIT(chspec) (CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX) + #define CH20MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_20 | \ + WL_CHANSPEC_CTL_SB_NONE | (((channel) <= CH_MAX_2G_CHANNEL) ? \ +@@ -192,13 +184,6 @@ typedef uint16 chanspec_t; + ((channel) - CH_10MHZ_APART) : 0) + #define UPPER_20_SB(channel) (((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? \ + ((channel) + CH_10MHZ_APART) : 0) +- +-#define LL_20_SB(channel) (((channel) > 3 * CH_10MHZ_APART) ? ((channel) - 3 * CH_10MHZ_APART) : 0) +-#define UU_20_SB(channel) (((channel) < (MAXCHANNEL - 3 * CH_10MHZ_APART)) ? \ +- ((channel) + 3 * CH_10MHZ_APART) : 0) +-#define LU_20_SB(channel) LOWER_20_SB(channel) +-#define UL_20_SB(channel) UPPER_20_SB(channel) +- + #define LOWER_40_SB(channel) ((channel) - CH_20MHZ_APART) + #define UPPER_40_SB(channel) ((channel) + CH_20MHZ_APART) + #define CHSPEC_WLCBANDUNIT(chspec) (CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX) +@@ -313,11 +298,6 @@ typedef uint16 chanspec_t; + + #define LCHSPEC_CREATE(chan, band, bw, sb) ((uint16)((chan) | (sb) | (bw) | (band))) + +-#define CH20MHZ_LCHSPEC(channel) \ +- (chanspec_t)((chanspec_t)(channel) | WL_LCHANSPEC_BW_20 | \ +- WL_LCHANSPEC_CTL_SB_NONE | (((channel) <= CH_MAX_2G_CHANNEL) ? \ +- WL_LCHANSPEC_BAND_2G : WL_LCHANSPEC_BAND_5G)) +- + #endif /* D11AC_IOTYPES */ + + /* +@@ -344,6 +324,21 @@ typedef uint16 chanspec_t; + */ + #define WF_CHAN_FACTOR_4_G 8000 /* 4.9 GHz band for Japan */ + ++/* defined rate in 500kbps */ ++#define WLC_MAXRATE 108 /* in 500kbps units */ ++#define WLC_RATE_1M 2 /* in 500kbps units */ ++#define WLC_RATE_2M 4 /* in 500kbps units */ ++#define WLC_RATE_5M5 11 /* in 500kbps units */ ++#define WLC_RATE_11M 22 /* in 500kbps units */ ++#define WLC_RATE_6M 12 /* in 500kbps units */ ++#define WLC_RATE_9M 18 /* in 500kbps units */ ++#define WLC_RATE_12M 24 /* in 500kbps units */ ++#define WLC_RATE_18M 36 /* in 500kbps units */ ++#define WLC_RATE_24M 48 /* in 500kbps units */ ++#define WLC_RATE_36M 72 /* in 500kbps units */ ++#define WLC_RATE_48M 96 /* in 500kbps units */ ++#define WLC_RATE_54M 108 /* in 500kbps units */ ++ + #define WLC_2G_25MHZ_OFFSET 5 /* 2.4GHz band channel offset */ + + /** +@@ -492,8 +487,4 @@ extern int wf_channel2mhz(uint channel, + */ + extern uint16 wf_channel2chspec(uint ctl_ch, uint bw); + +-extern uint wf_channel2freq(uint channel); +-extern uint wf_freq2channel(uint freq); +- +- + #endif /* _bcmwifi_channels_h_ */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/bcmwifi_rates.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcmwifi_rates.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/bcmwifi_rates.h 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/bcmwifi_rates.h 2014-02-15 00:43:44.794014114 +0100 +@@ -1,7 +1,7 @@ + /* + * Indices for 802.11 a/b/g/n/ac 1-3 chain symmetric transmit rates + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -21,7 +21,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: bcmwifi_rates.h 5187 2012-06-29 06:17:50Z $ ++ * $Id: bcmwifi_rates.h 252708 2011-04-12 06:45:56Z $ + */ + + #ifndef _bcmwifi_rates_h_ +@@ -48,7 +48,8 @@ typedef enum wl_tx_bw { + WL_TX_BW_80, + WL_TX_BW_20IN40, + WL_TX_BW_20IN80, +- WL_TX_BW_40IN80 ++ WL_TX_BW_40IN80, ++ WL_TX_BW_ALL + } wl_tx_bw_t; + + +@@ -60,8 +61,7 @@ typedef enum wl_tx_mode { + WL_TX_MODE_NONE, + WL_TX_MODE_STBC, + WL_TX_MODE_CDD, +- WL_TX_MODE_TXBF, +- WL_NUM_TX_MODES ++ WL_TX_MODE_SDM + } wl_tx_mode_t; + + +@@ -83,9 +83,9 @@ typedef enum wl_tx_nss { + + typedef enum clm_rates { + /************ +- * 1 chain * +- ************ +- */ ++ * 1 chain * ++ ************ ++ */ + + /* 1 Stream */ + WL_RATE_1X1_DSSS_1 = 0, +@@ -124,9 +124,9 @@ typedef enum clm_rates { + + + /************ +- * 2 chains * +- ************ +- */ ++ * 2 chains * ++ ************ ++ */ + + /* 1 Stream expanded + 1 */ + WL_RATE_1X2_DSSS_1 = 22, +@@ -204,10 +204,11 @@ typedef enum clm_rates { + WL_RATE_2X2_VHT8SS2 = 62, + WL_RATE_2X2_VHT9SS2 = 63, + ++ + /************ +- * 3 chains * +- ************ +- */ ++ * 3 chains * ++ ************ ++ */ + + /* 1 Stream expanded + 2 */ + WL_RATE_1X3_DSSS_1 = 64, +@@ -306,146 +307,10 @@ typedef enum clm_rates { + WL_RATE_3X3_VHT8SS3 = 114, + WL_RATE_3X3_VHT9SS3 = 115, + +- +- /**************************** +- * TX Beamforming, 2 chains * +- **************************** +- */ +- +- /* 1 Stream expanded + 1 */ +- +- WL_RATE_1X2_TXBF_OFDM_6 = 116, +- WL_RATE_1X2_TXBF_OFDM_9 = 117, +- WL_RATE_1X2_TXBF_OFDM_12 = 118, +- WL_RATE_1X2_TXBF_OFDM_18 = 119, +- WL_RATE_1X2_TXBF_OFDM_24 = 120, +- WL_RATE_1X2_TXBF_OFDM_36 = 121, +- WL_RATE_1X2_TXBF_OFDM_48 = 122, +- WL_RATE_1X2_TXBF_OFDM_54 = 123, +- +- WL_RATE_1X2_TXBF_MCS0 = 124, +- WL_RATE_1X2_TXBF_MCS1 = 125, +- WL_RATE_1X2_TXBF_MCS2 = 126, +- WL_RATE_1X2_TXBF_MCS3 = 127, +- WL_RATE_1X2_TXBF_MCS4 = 128, +- WL_RATE_1X2_TXBF_MCS5 = 129, +- WL_RATE_1X2_TXBF_MCS6 = 130, +- WL_RATE_1X2_TXBF_MCS7 = 131, +- +- WL_RATE_1X2_TXBF_VHT0SS1 = 124, +- WL_RATE_1X2_TXBF_VHT1SS1 = 125, +- WL_RATE_1X2_TXBF_VHT2SS1 = 126, +- WL_RATE_1X2_TXBF_VHT3SS1 = 127, +- WL_RATE_1X2_TXBF_VHT4SS1 = 128, +- WL_RATE_1X2_TXBF_VHT5SS1 = 129, +- WL_RATE_1X2_TXBF_VHT6SS1 = 130, +- WL_RATE_1X2_TXBF_VHT7SS1 = 131, +- WL_RATE_1X2_TXBF_VHT8SS1 = 132, +- WL_RATE_1X2_TXBF_VHT9SS1 = 133, +- +- /* 2 Streams */ +- +- WL_RATE_2X2_TXBF_SDM_MCS8 = 134, +- WL_RATE_2X2_TXBF_SDM_MCS9 = 135, +- WL_RATE_2X2_TXBF_SDM_MCS10 = 136, +- WL_RATE_2X2_TXBF_SDM_MCS11 = 137, +- WL_RATE_2X2_TXBF_SDM_MCS12 = 138, +- WL_RATE_2X2_TXBF_SDM_MCS13 = 139, +- WL_RATE_2X2_TXBF_SDM_MCS14 = 140, +- WL_RATE_2X2_TXBF_SDM_MCS15 = 141, +- +- WL_RATE_2X2_TXBF_VHT0SS2 = 134, +- WL_RATE_2X2_TXBF_VHT1SS2 = 135, +- WL_RATE_2X2_TXBF_VHT2SS2 = 136, +- WL_RATE_2X2_TXBF_VHT3SS2 = 137, +- WL_RATE_2X2_TXBF_VHT4SS2 = 138, +- WL_RATE_2X2_TXBF_VHT5SS2 = 139, +- WL_RATE_2X2_TXBF_VHT6SS2 = 140, +- WL_RATE_2X2_TXBF_VHT7SS2 = 141, +- +- +- /**************************** +- * TX Beamforming, 3 chains * +- **************************** +- */ +- +- /* 1 Stream expanded + 2 */ +- +- WL_RATE_1X3_TXBF_OFDM_6 = 142, +- WL_RATE_1X3_TXBF_OFDM_9 = 143, +- WL_RATE_1X3_TXBF_OFDM_12 = 144, +- WL_RATE_1X3_TXBF_OFDM_18 = 145, +- WL_RATE_1X3_TXBF_OFDM_24 = 146, +- WL_RATE_1X3_TXBF_OFDM_36 = 147, +- WL_RATE_1X3_TXBF_OFDM_48 = 148, +- WL_RATE_1X3_TXBF_OFDM_54 = 149, +- +- WL_RATE_1X3_TXBF_MCS0 = 150, +- WL_RATE_1X3_TXBF_MCS1 = 151, +- WL_RATE_1X3_TXBF_MCS2 = 152, +- WL_RATE_1X3_TXBF_MCS3 = 153, +- WL_RATE_1X3_TXBF_MCS4 = 154, +- WL_RATE_1X3_TXBF_MCS5 = 155, +- WL_RATE_1X3_TXBF_MCS6 = 156, +- WL_RATE_1X3_TXBF_MCS7 = 157, +- +- WL_RATE_1X3_TXBF_VHT0SS1 = 150, +- WL_RATE_1X3_TXBF_VHT1SS1 = 151, +- WL_RATE_1X3_TXBF_VHT2SS1 = 152, +- WL_RATE_1X3_TXBF_VHT3SS1 = 153, +- WL_RATE_1X3_TXBF_VHT4SS1 = 154, +- WL_RATE_1X3_TXBF_VHT5SS1 = 155, +- WL_RATE_1X3_TXBF_VHT6SS1 = 156, +- WL_RATE_1X3_TXBF_VHT7SS1 = 157, +- WL_RATE_1X3_TXBF_VHT8SS1 = 158, +- WL_RATE_1X3_TXBF_VHT9SS1 = 159, +- +- /* 2 Streams expanded + 1 */ +- +- WL_RATE_2X3_TXBF_SDM_MCS8 = 160, +- WL_RATE_2X3_TXBF_SDM_MCS9 = 161, +- WL_RATE_2X3_TXBF_SDM_MCS10 = 162, +- WL_RATE_2X3_TXBF_SDM_MCS11 = 163, +- WL_RATE_2X3_TXBF_SDM_MCS12 = 164, +- WL_RATE_2X3_TXBF_SDM_MCS13 = 165, +- WL_RATE_2X3_TXBF_SDM_MCS14 = 166, +- WL_RATE_2X3_TXBF_SDM_MCS15 = 167, +- +- WL_RATE_2X3_TXBF_VHT0SS2 = 160, +- WL_RATE_2X3_TXBF_VHT1SS2 = 161, +- WL_RATE_2X3_TXBF_VHT2SS2 = 162, +- WL_RATE_2X3_TXBF_VHT3SS2 = 163, +- WL_RATE_2X3_TXBF_VHT4SS2 = 164, +- WL_RATE_2X3_TXBF_VHT5SS2 = 165, +- WL_RATE_2X3_TXBF_VHT6SS2 = 166, +- WL_RATE_2X3_TXBF_VHT7SS2 = 167, +- WL_RATE_2X3_TXBF_VHT8SS2 = 168, +- WL_RATE_2X3_TXBF_VHT9SS2 = 169, +- +- /* 3 Streams */ +- +- WL_RATE_3X3_TXBF_SDM_MCS16 = 170, +- WL_RATE_3X3_TXBF_SDM_MCS17 = 171, +- WL_RATE_3X3_TXBF_SDM_MCS18 = 172, +- WL_RATE_3X3_TXBF_SDM_MCS19 = 173, +- WL_RATE_3X3_TXBF_SDM_MCS20 = 174, +- WL_RATE_3X3_TXBF_SDM_MCS21 = 175, +- WL_RATE_3X3_TXBF_SDM_MCS22 = 176, +- WL_RATE_3X3_TXBF_SDM_MCS23 = 177, +- +- WL_RATE_3X3_TXBF_VHT0SS3 = 170, +- WL_RATE_3X3_TXBF_VHT1SS3 = 171, +- WL_RATE_3X3_TXBF_VHT2SS3 = 172, +- WL_RATE_3X3_TXBF_VHT3SS3 = 173, +- WL_RATE_3X3_TXBF_VHT4SS3 = 174, +- WL_RATE_3X3_TXBF_VHT5SS3 = 175, +- WL_RATE_3X3_TXBF_VHT6SS3 = 176, +- WL_RATE_3X3_TXBF_VHT7SS3 = 177 ++ /* Number of rate codes */ ++ WL_NUMRATES = 116 + } clm_rates_t; + +-/* Number of rate codes */ +-#define WL_NUMRATES 178 +- + #ifdef __cplusplus + } + #endif /* __cplusplus */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/dhdioctl.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/dhdioctl.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/dhdioctl.h 2014-01-27 01:30:30.101433269 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/dhdioctl.h 2014-02-15 00:43:44.793014092 +0100 +@@ -5,7 +5,7 @@ + * + * Definitions subject to change without notice. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -25,7 +25,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: dhdioctl.h 419132 2013-08-19 21:33:05Z $ ++ * $Id: dhdioctl.h 354894 2012-09-04 12:34:07Z $ + */ + + #ifndef _dhdioctl_h_ +@@ -85,13 +85,15 @@ enum { + #define DHD_GLOM_VAL 0x0400 + #define DHD_EVENT_VAL 0x0800 + #define DHD_BTA_VAL 0x1000 ++#if 0 && (NDISVER >= 0x0630) && 1 ++#define DHD_SCAN_VAL 0x2000 ++#else + #define DHD_ISCAN_VAL 0x2000 ++#endif + #define DHD_ARPOE_VAL 0x4000 + #define DHD_REORDER_VAL 0x8000 +-#define DHD_WL_VAL 0x10000 +-#define DHD_NOCHECKDIED_VAL 0x20000 /* UTF WAR */ +-#define DHD_WL_VAL2 0x40000 +-#define DHD_PNO_VAL 0x80000 ++#define DHD_IW_VAL 0x10000 ++#define DHD_CFG_VAL 0x20000 + + #ifdef SDTEST + /* For pktgen iovar */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/epivers.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/epivers.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/epivers.h 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/epivers.h 2014-02-15 00:43:44.794014114 +0100 +@@ -1,5 +1,5 @@ + /* +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -28,28 +28,28 @@ + + #define EPI_MAJOR_VERSION 1 + +-#define EPI_MINOR_VERSION 88 ++#define EPI_MINOR_VERSION 28 + +-#define EPI_RC_NUMBER 45 ++#define EPI_RC_NUMBER 23 + + #define EPI_INCREMENTAL_NUMBER 0 + + #define EPI_BUILD_NUMBER 0 + +-#define EPI_VERSION 1, 88, 45, 0 ++#define EPI_VERSION 1, 28, 23, 0 + +-#define EPI_VERSION_NUM 0x01582d00 ++#define EPI_VERSION_NUM 0x011c1700 + +-#define EPI_VERSION_DEV 1.88.45 ++#define EPI_VERSION_DEV 1.28.23 + + /* Driver Version String, ASCII, 32 chars max */ + #ifdef BCMINTERNAL +-#define EPI_VERSION_STR "1.88.45 (r BCMINT)" ++#define EPI_VERSION_STR "1.28.23.3 (r BCMINT)" + #else + #ifdef WLTEST +-#define EPI_VERSION_STR "1.88.45 (r WLTEST)" ++#define EPI_VERSION_STR "1.28.23.3 (r WLTEST)" + #else +-#define EPI_VERSION_STR "1.88.45 (r)" ++#define EPI_VERSION_STR "1.28.23.3 (r)" + #endif + #endif /* BCMINTERNAL */ + +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/hndpmu.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/hndpmu.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/hndpmu.h 2014-01-27 01:30:30.101433269 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/hndpmu.h 2014-02-15 00:43:44.793014092 +0100 +@@ -1,7 +1,7 @@ + /* + * HND SiliconBackplane PMU support. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -21,7 +21,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: hndpmu.h 385540 2013-02-15 23:14:50Z $ ++ * $Id: hndpmu.h 241182 2011-02-17 21:50:03Z $ + */ + + #ifndef _hndpmu_h_ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/hndrte_armtrap.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/hndrte_armtrap.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/hndrte_armtrap.h 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/hndrte_armtrap.h 2014-02-15 00:43:44.794014114 +0100 +@@ -1,7 +1,7 @@ + /* + * HNDRTE arm trap handling. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/hndrte_cons.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/hndrte_cons.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/hndrte_cons.h 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/hndrte_cons.h 2014-02-15 00:43:44.794014114 +0100 +@@ -1,7 +1,7 @@ + /* + * Console support for hndrte. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -21,7 +21,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: hndrte_cons.h 383834 2013-02-07 23:21:51Z $ ++ * $Id: hndrte_cons.h 300516 2011-12-04 17:39:44Z $ + */ + #ifndef _HNDRTE_CONS_H + #define _HNDRTE_CONS_H +@@ -64,6 +64,4 @@ typedef struct { + char cbuf[CBUF_LEN]; + } hndrte_cons_t; + +-hndrte_cons_t *hndrte_get_active_cons_state(void); +- + #endif /* _HNDRTE_CONS_H */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/hndsoc.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/hndsoc.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/hndsoc.h 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/hndsoc.h 2014-02-15 00:43:44.794014114 +0100 +@@ -1,7 +1,7 @@ + /* + * Broadcom HND chip & on-chip-interconnect-related definitions. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -21,7 +21,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: hndsoc.h 365041 2012-10-26 09:10:35Z $ ++ * $Id: hndsoc.h 309193 2012-01-19 00:03:57Z $ + */ + + #ifndef _HNDSOC_H +@@ -46,8 +46,10 @@ + + #define SI_WRAP_BASE 0x18100000 /* Wrapper space base */ + #define SI_CORE_SIZE 0x1000 /* each core gets 4Kbytes for registers */ +- +-#define SI_MAXCORES 32 /* NorthStar has more cores */ ++#define SI_MAXCORES 16 /* Max cores (this is arbitrary, for software ++ * convenience and could be changed if we ++ * make any larger chips ++ */ + + #define SI_FASTRAM 0x19000000 /* On-chip RAM on chips that also have DDR */ + #define SI_FASTRAM_SWAPPED 0x19800000 +@@ -57,13 +59,6 @@ + #define SI_ARMCM3_ROM 0x1e000000 /* ARM Cortex-M3 ROM */ + #define SI_FLASH1 0x1fc00000 /* MIPS Flash Region 1 */ + #define SI_FLASH1_SZ 0x00400000 /* MIPS Size of Flash Region 1 */ +-#define SI_FLASH_WINDOW 0x01000000 /* Flash XIP Window */ +- +-#define SI_NS_NANDFLASH 0x1c000000 /* NorthStar NAND flash base */ +-#define SI_NS_NORFLASH 0x1e000000 /* NorthStar NOR flash base */ +-#define SI_NS_ROM 0xfffd0000 /* NorthStar ROM */ +-#define SI_NS_FLASH_WINDOW 0x02000000 /* Flash XIP Window */ +- + #define SI_ARM7S_ROM 0x20000000 /* ARM7TDMI-S ROM */ + #define SI_ARMCR4_ROM 0x000f0000 /* ARM Cortex-R4 ROM */ + #define SI_ARMCM3_SRAM2 0x60000000 /* ARM Cortex-M3 SRAM Region 2 */ +@@ -152,21 +147,7 @@ + */ + + #define CC_4706_CORE_ID 0x500 /* chipcommon core */ +-#define NS_PCIEG2_CORE_ID 0x501 /* PCIE Gen 2 core */ +-#define NS_DMA_CORE_ID 0x502 /* DMA core */ +-#define NS_SDIO3_CORE_ID 0x503 /* SDIO3 core */ +-#define NS_USB20_CORE_ID 0x504 /* USB2.0 core */ +-#define NS_USB30_CORE_ID 0x505 /* USB3.0 core */ +-#define NS_A9JTAG_CORE_ID 0x506 /* ARM Cortex A9 JTAG core */ +-#define NS_DDR23_CORE_ID 0x507 /* Denali DDR2/DDR3 memory controller */ +-#define NS_ROM_CORE_ID 0x508 /* ROM core */ +-#define NS_NAND_CORE_ID 0x509 /* NAND flash controller core */ +-#define NS_QSPI_CORE_ID 0x50a /* SPI flash controller core */ +-#define NS_CCB_CORE_ID 0x50b /* ChipcommonB core */ + #define SOCRAM_4706_CORE_ID 0x50e /* internal memory core */ +-#define NS_SOCRAM_CORE_ID SOCRAM_4706_CORE_ID +-#define ARMCA9_CORE_ID 0x510 /* ARM Cortex A9 core (ihost) */ +-#define NS_IHOST_CORE_ID ARMCA9_CORE_ID /* ARM Cortex A9 core (ihost) */ + #define GMAC_COMMON_4706_CORE_ID 0x5dc /* Gigabit MAC core */ + #define GMAC_4706_CORE_ID 0x52d /* Gigabit MAC core */ + #define AMEMC_CORE_ID 0x52e /* DDR1/2 memory controller core */ +@@ -191,7 +172,6 @@ + #define SOCI_SB 0 + #define SOCI_AI 1 + #define SOCI_UBUS 2 +-#define SOCI_NAI 3 + + /* Common core control flags */ + #define SICF_BIST_EN 0x8000 +@@ -207,14 +187,6 @@ + #define SISF_DMA64 0x1000 + #define SISF_CORE_BITS 0x0fff + +-/* Norstar core status flags */ +-#define SISF_NS_BOOTDEV_MASK 0x0003 /* ROM core */ +-#define SISF_NS_BOOTDEV_NOR 0x0000 /* ROM core */ +-#define SISF_NS_BOOTDEV_NAND 0x0001 /* ROM core */ +-#define SISF_NS_BOOTDEV_ROM 0x0002 /* ROM core */ +-#define SISF_NS_BOOTDEV_OFFLOAD 0x0003 /* ROM core */ +-#define SISF_NS_SKUVEC_MASK 0x000c /* ROM core */ +- + /* A register that is common to all cores to + * communicate w/PMU regarding clock control. + */ +@@ -260,18 +232,4 @@ + #define BISZ_BSSEND_IDX 6 /* 6: bss end */ + #define BISZ_SIZE 7 /* descriptor size in 32-bit integers */ + +-/* Boot/Kernel related defintion and functions */ +-#define SOC_BOOTDEV_ROM 0x00000001 +-#define SOC_BOOTDEV_PFLASH 0x00000002 +-#define SOC_BOOTDEV_SFLASH 0x00000004 +-#define SOC_BOOTDEV_NANDFLASH 0x00000008 +- +-#define SOC_KNLDEV_NORFLASH 0x00000002 +-#define SOC_KNLDEV_NANDFLASH 0x00000004 +- +-#ifndef _LANGUAGE_ASSEMBLY +-int soc_boot_dev(void *sih); +-int soc_knl_dev(void *sih); +-#endif /* _LANGUAGE_ASSEMBLY */ +- + #endif /* _HNDSOC_H */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/linux_osl.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/linux_osl.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/linux_osl.h 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/linux_osl.h 2014-02-15 00:43:44.794014114 +0100 +@@ -1,7 +1,7 @@ + /* + * Linux OS Independent Layer + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -21,7 +21,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: linux_osl.h 411126 2013-07-05 01:22:09Z $ ++ * $Id: linux_osl.h 354452 2012-08-31 04:59:17Z $ + */ + + #ifndef _linux_osl_h_ +@@ -67,9 +67,6 @@ extern void osl_assert(const char *exp, + #define OSL_DELAY(usec) osl_delay(usec) + extern void osl_delay(uint usec); + +-#define OSL_SLEEP(ms) osl_sleep(ms) +-extern void osl_sleep(uint ms); +- + #define OSL_PCMCIA_READ_ATTR(osh, offset, buf, size) \ + osl_pcmcia_read_attr((osh), (offset), (buf), (size)) + #define OSL_PCMCIA_WRITE_ATTR(osh, offset, buf, size) \ +@@ -95,6 +92,7 @@ extern struct pci_dev *osl_pci_device(os + /* Pkttag flag should be part of public information */ + typedef struct { + bool pkttag; ++ uint pktalloced; /* Number of allocated packet buffers */ + bool mmbus; /* Bus supports memory-mapped register accesses */ + pktfree_cb_fn_t tx_fn; /* Callback function for PKTFREE */ + void *tx_ctx; /* Context to the callback function */ +@@ -141,8 +139,7 @@ extern void osl_dma_free_consistent(osl_ + /* map/unmap shared (dma-able) memory */ + #define DMA_UNMAP(osh, pa, size, direction, p, dmah) \ + osl_dma_unmap((osh), (pa), (size), (direction)) +-extern uint osl_dma_map(osl_t *osh, void *va, uint size, int direction, void *p, +- hnddma_seg_map_t *txp_dmah); ++extern uint osl_dma_map(osl_t *osh, void *va, uint size, int direction); + extern void osl_dma_unmap(osl_t *osh, uint pa, uint size, int direction); + + /* API for DMA addressing capability */ +@@ -227,9 +224,6 @@ extern int osl_error(int bcmerror); + #define OSL_UNCACHED(va) ((void *)va) + #define OSL_CACHED(va) ((void *)va) + +-/* ARM NorthStar */ +-#define OSL_CACHE_FLUSH(va, len) +- + #define OSL_PREF_RANGE_LD(va, sz) + #define OSL_PREF_RANGE_ST(va, sz) + +@@ -262,77 +256,30 @@ extern int osl_error(int bcmerror); + #include /* use current 2.4.x calling conventions */ + + /* packet primitives */ +-#ifdef BCMDBG_CTRACE +-#define PKTGET(osh, len, send) osl_pktget((osh), (len), __LINE__, __FILE__) +-#define PKTDUP(osh, skb) osl_pktdup((osh), (skb), __LINE__, __FILE__) +-#else + #define PKTGET(osh, len, send) osl_pktget((osh), (len)) + #define PKTDUP(osh, skb) osl_pktdup((osh), (skb)) +-#endif /* BCMDBG_CTRACE */ + #define PKTLIST_DUMP(osh, buf) + #define PKTDBG_TRACE(osh, pkt, bit) + #define PKTFREE(osh, skb, send) osl_pktfree((osh), (skb), (send)) + #ifdef CONFIG_DHD_USE_STATIC_BUF + #define PKTGET_STATIC(osh, len, send) osl_pktget_static((osh), (len)) + #define PKTFREE_STATIC(osh, skb, send) osl_pktfree_static((osh), (skb), (send)) +-#else +-#define PKTGET_STATIC PKTGET +-#define PKTFREE_STATIC PKTFREE + #endif /* CONFIG_DHD_USE_STATIC_BUF */ + #define PKTDATA(osh, skb) (((struct sk_buff*)(skb))->data) + #define PKTLEN(osh, skb) (((struct sk_buff*)(skb))->len) + #define PKTHEADROOM(osh, skb) (PKTDATA(osh, skb)-(((struct sk_buff*)(skb))->head)) +-#define PKTTAILROOM(osh, skb) skb_tailroom((struct sk_buff*)(skb)) +-#define PKTPADTAILROOM(osh, skb, padlen) osh_pktpadtailroom((osh), (skb), (padlen)) ++#define PKTTAILROOM(osh, skb) ((((struct sk_buff*)(skb))->end)-(((struct sk_buff*)(skb))->tail)) + #define PKTNEXT(osh, skb) (((struct sk_buff*)(skb))->next) + #define PKTSETNEXT(osh, skb, x) (((struct sk_buff*)(skb))->next = (struct sk_buff*)(x)) + #define PKTSETLEN(osh, skb, len) __skb_trim((struct sk_buff*)(skb), (len)) + #define PKTPUSH(osh, skb, bytes) skb_push((struct sk_buff*)(skb), (bytes)) + #define PKTPULL(osh, skb, bytes) skb_pull((struct sk_buff*)(skb), (bytes)) + #define PKTTAG(skb) ((void*)(((struct sk_buff*)(skb))->cb)) ++#define PKTALLOCED(osh) ((osl_pubinfo_t *)(osh))->pktalloced + #define PKTSETPOOL(osh, skb, x, y) do {} while (0) + #define PKTPOOL(osh, skb) FALSE + #define PKTSHRINK(osh, m) (m) + +-#ifdef BCMDBG_CTRACE +-#define DEL_CTRACE(zosh, zskb) { \ +- unsigned long zflags; \ +- spin_lock_irqsave(&(zosh)->ctrace_lock, zflags); \ +- list_del(&(zskb)->ctrace_list); \ +- (zosh)->ctrace_num--; \ +- (zskb)->ctrace_start = 0; \ +- (zskb)->ctrace_count = 0; \ +- spin_unlock_irqrestore(&(zosh)->ctrace_lock, zflags); \ +-} +- +-#define UPDATE_CTRACE(zskb, zfile, zline) { \ +- struct sk_buff *_zskb = (struct sk_buff *)(zskb); \ +- if (_zskb->ctrace_count < CTRACE_NUM) { \ +- _zskb->func[_zskb->ctrace_count] = zfile; \ +- _zskb->line[_zskb->ctrace_count] = zline; \ +- _zskb->ctrace_count++; \ +- } \ +- else { \ +- _zskb->func[_zskb->ctrace_start] = zfile; \ +- _zskb->line[_zskb->ctrace_start] = zline; \ +- _zskb->ctrace_start++; \ +- if (_zskb->ctrace_start >= CTRACE_NUM) \ +- _zskb->ctrace_start = 0; \ +- } \ +-} +- +-#define ADD_CTRACE(zosh, zskb, zfile, zline) { \ +- unsigned long zflags; \ +- spin_lock_irqsave(&(zosh)->ctrace_lock, zflags); \ +- list_add(&(zskb)->ctrace_list, &(zosh)->ctrace_list); \ +- (zosh)->ctrace_num++; \ +- UPDATE_CTRACE(zskb, zfile, zline); \ +- spin_unlock_irqrestore(&(zosh)->ctrace_lock, zflags); \ +-} +- +-#define PKTCALLER(zskb) UPDATE_CTRACE((struct sk_buff *)zskb, (char *)__FUNCTION__, __LINE__) +-#endif /* BCMDBG_CTRACE */ +- + #ifdef CTFPOOL + #define CTFPOOL_REFILL_THRESH 3 + typedef struct ctfpool { +@@ -346,117 +293,66 @@ typedef struct ctfpool { + uint fast_frees; + uint slow_allocs; + } ctfpool_t; +- +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) +-#define FASTBUF (1 << 0) +-#define PKTSETFAST(osh, skb) ((((struct sk_buff*)(skb))->pktc_flags) |= FASTBUF) +-#define PKTCLRFAST(osh, skb) ((((struct sk_buff*)(skb))->pktc_flags) &= (~FASTBUF)) +-#define PKTISFAST(osh, skb) ((((struct sk_buff*)(skb))->pktc_flags) & FASTBUF) +-#define PKTFAST(osh, skb) (((struct sk_buff*)(skb))->pktc_flags) +-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) + #define FASTBUF (1 << 16) ++#define CTFBUF (1 << 17) + #define PKTSETFAST(osh, skb) ((((struct sk_buff*)(skb))->mac_len) |= FASTBUF) + #define PKTCLRFAST(osh, skb) ((((struct sk_buff*)(skb))->mac_len) &= (~FASTBUF)) ++#define PKTSETCTF(osh, skb) ((((struct sk_buff*)(skb))->mac_len) |= CTFBUF) ++#define PKTCLRCTF(osh, skb) ((((struct sk_buff*)(skb))->mac_len) &= (~CTFBUF)) + #define PKTISFAST(osh, skb) ((((struct sk_buff*)(skb))->mac_len) & FASTBUF) ++#define PKTISCTF(osh, skb) ((((struct sk_buff*)(skb))->mac_len) & CTFBUF) + #define PKTFAST(osh, skb) (((struct sk_buff*)(skb))->mac_len) + #else + #define FASTBUF (1 << 0) ++#define CTFBUF (1 << 1) + #define PKTSETFAST(osh, skb) ((((struct sk_buff*)(skb))->__unused) |= FASTBUF) + #define PKTCLRFAST(osh, skb) ((((struct sk_buff*)(skb))->__unused) &= (~FASTBUF)) ++#define PKTSETCTF(osh, skb) ((((struct sk_buff*)(skb))->__unused) |= CTFBUF) ++#define PKTCLRCTF(osh, skb) ((((struct sk_buff*)(skb))->__unused) &= (~CTFBUF)) + #define PKTISFAST(osh, skb) ((((struct sk_buff*)(skb))->__unused) & FASTBUF) ++#define PKTISCTF(osh, skb) ((((struct sk_buff*)(skb))->__unused) & CTFBUF) + #define PKTFAST(osh, skb) (((struct sk_buff*)(skb))->__unused) + #endif /* 2.6.22 */ + +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) +-#define CTFPOOLPTR(osh, skb) (((struct sk_buff*)(skb))->ctfpool) +-#define CTFPOOLHEAD(osh, skb) (((ctfpool_t *)((struct sk_buff*)(skb))->ctfpool)->head) +-#else + #define CTFPOOLPTR(osh, skb) (((struct sk_buff*)(skb))->sk) + #define CTFPOOLHEAD(osh, skb) (((ctfpool_t *)((struct sk_buff*)(skb))->sk)->head) +-#endif + + extern void *osl_ctfpool_add(osl_t *osh); + extern void osl_ctfpool_replenish(osl_t *osh, uint thresh); + extern int32 osl_ctfpool_init(osl_t *osh, uint numobj, uint size); + extern void osl_ctfpool_cleanup(osl_t *osh); + extern void osl_ctfpool_stats(osl_t *osh, void *b); +-#else /* CTFPOOL */ +-#define PKTSETFAST(osh, skb) +-#define PKTCLRFAST(osh, skb) +-#define PKTISFAST(osh, skb) (FALSE) + #endif /* CTFPOOL */ + +-#define PKTSETCTF(osh, skb) +-#define PKTCLRCTF(osh, skb) +-#define PKTISCTF(osh, skb) (FALSE) + + #ifdef HNDCTF +- +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) +-#define SKIPCT (1 << 2) +-#define CHAINED (1 << 3) +-#define PKTSETSKIPCT(osh, skb) (((struct sk_buff*)(skb))->pktc_flags |= SKIPCT) +-#define PKTCLRSKIPCT(osh, skb) (((struct sk_buff*)(skb))->pktc_flags &= (~SKIPCT)) +-#define PKTSKIPCT(osh, skb) (((struct sk_buff*)(skb))->pktc_flags & SKIPCT) +-#define PKTSETCHAINED(osh, skb) (((struct sk_buff*)(skb))->pktc_flags |= CHAINED) +-#define PKTCLRCHAINED(osh, skb) (((struct sk_buff*)(skb))->pktc_flags &= (~CHAINED)) +-#define PKTISCHAINED(skb) (((struct sk_buff*)(skb))->pktc_flags & CHAINED) +-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) + #define SKIPCT (1 << 18) +-#define CHAINED (1 << 19) + #define PKTSETSKIPCT(osh, skb) (((struct sk_buff*)(skb))->mac_len |= SKIPCT) + #define PKTCLRSKIPCT(osh, skb) (((struct sk_buff*)(skb))->mac_len &= (~SKIPCT)) + #define PKTSKIPCT(osh, skb) (((struct sk_buff*)(skb))->mac_len & SKIPCT) +-#define PKTSETCHAINED(osh, skb) (((struct sk_buff*)(skb))->mac_len |= CHAINED) +-#define PKTCLRCHAINED(osh, skb) (((struct sk_buff*)(skb))->mac_len &= (~CHAINED)) +-#define PKTISCHAINED(skb) (((struct sk_buff*)(skb))->mac_len & CHAINED) + #else /* 2.6.22 */ + #define SKIPCT (1 << 2) +-#define CHAINED (1 << 3) + #define PKTSETSKIPCT(osh, skb) (((struct sk_buff*)(skb))->__unused |= SKIPCT) + #define PKTCLRSKIPCT(osh, skb) (((struct sk_buff*)(skb))->__unused &= (~SKIPCT)) + #define PKTSKIPCT(osh, skb) (((struct sk_buff*)(skb))->__unused & SKIPCT) +-#define PKTSETCHAINED(osh, skb) (((struct sk_buff*)(skb))->__unused |= CHAINED) +-#define PKTCLRCHAINED(osh, skb) (((struct sk_buff*)(skb))->__unused &= (~CHAINED)) +-#define PKTISCHAINED(skb) (((struct sk_buff*)(skb))->__unused & CHAINED) + #endif /* 2.6.22 */ +-typedef struct ctf_mark { +- uint32 value; +-} ctf_mark_t; +-#define CTF_MARK(m) (m.value) + #else /* HNDCTF */ + #define PKTSETSKIPCT(osh, skb) + #define PKTCLRSKIPCT(osh, skb) + #define PKTSKIPCT(osh, skb) +-#define CTF_MARK(m) 0 + #endif /* HNDCTF */ + + extern void osl_pktfree(osl_t *osh, void *skb, bool send); + extern void *osl_pktget_static(osl_t *osh, uint len); + extern void osl_pktfree_static(osl_t *osh, void *skb, bool send); +-extern int osh_pktpadtailroom(osl_t *osh, void* skb, int pad); + +-#ifdef BCMDBG_CTRACE +-#define PKT_CTRACE_DUMP(osh, b) osl_ctrace_dump((osh), (b)) +-extern void *osl_pktget(osl_t *osh, uint len, int line, char *file); +-extern void *osl_pkt_frmnative(osl_t *osh, void *skb, int line, char *file); +-extern int osl_pkt_is_frmnative(osl_t *osh, struct sk_buff *pkt); +-extern void *osl_pktdup(osl_t *osh, void *skb, int line, char *file); +-struct bcmstrbuf; +-extern void osl_ctrace_dump(osl_t *osh, struct bcmstrbuf *b); +-#else + extern void *osl_pkt_frmnative(osl_t *osh, void *skb); + extern void *osl_pktget(osl_t *osh, uint len); + extern void *osl_pktdup(osl_t *osh, void *skb); +-#endif /* BCMDBG_CTRACE */ + extern struct sk_buff *osl_pkt_tonative(osl_t *osh, void *pkt); +-#ifdef BCMDBG_CTRACE +-#define PKTFRMNATIVE(osh, skb) osl_pkt_frmnative(((osl_t *)osh), \ +- (struct sk_buff*)(skb), __LINE__, __FILE__) +-#define PKTISFRMNATIVE(osh, skb) osl_pkt_is_frmnative((osl_t *)(osh), (struct sk_buff *)(skb)) +-#else + #define PKTFRMNATIVE(osh, skb) osl_pkt_frmnative(((osl_t *)osh), (struct sk_buff*)(skb)) +-#endif /* BCMDBG_CTRACE */ + #define PKTTONATIVE(osh, pkt) osl_pkt_tonative((osl_t *)(osh), (pkt)) + + #define PKTLINK(skb) (((struct sk_buff*)(skb))->prev) +@@ -469,24 +365,8 @@ extern struct sk_buff *osl_pkt_tonative( + /* PKTSETSUMNEEDED and PKTSUMGOOD are not possible because skb->ip_summed is overloaded */ + #define PKTSHARED(skb) (((struct sk_buff*)(skb))->cloned) + +-#ifdef CONFIG_NF_CONNTRACK_MARK +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) +-#define PKTMARK(p) (((struct sk_buff *)(p))->mark) +-#define PKTSETMARK(p, m) ((struct sk_buff *)(p))->mark = (m) +-#else /* !2.6.0 */ +-#define PKTMARK(p) (((struct sk_buff *)(p))->nfmark) +-#define PKTSETMARK(p, m) ((struct sk_buff *)(p))->nfmark = (m) +-#endif /* 2.6.0 */ +-#else /* CONFIG_NF_CONNTRACK_MARK */ +-#define PKTMARK(p) 0 +-#define PKTSETMARK(p, m) +-#endif /* CONFIG_NF_CONNTRACK_MARK */ +- +-#define PKTALLOCED(osh) osl_pktalloced(osh) +-extern uint osl_pktalloced(osl_t *osh); +- + #define DMA_MAP(osh, va, size, direction, p, dmah) \ +- osl_dma_map((osh), (va), (size), (direction), (p), (dmah)) ++ osl_dma_map((osh), (va), (size), (direction)) + + #ifdef PKTC + /* Use 8 bytes of skb tstamp field to store below info */ +@@ -495,52 +375,33 @@ struct chain_node { + unsigned int flags:3, pkts:9, bytes:20; + }; + +-#define CHAIN_NODE(skb) ((struct chain_node*)(((struct sk_buff*)skb)->pktc_cb)) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) ++#define CHAIN_NODE(skb) ((struct chain_node*)&(((struct sk_buff*)skb)->tstamp)) ++#else ++#define CHAIN_NODE(skb) ((struct chain_node*)&(((struct sk_buff*)skb)->stamp)) ++#endif + +-#define PKTCSETATTR(s, f, p, b) ({CHAIN_NODE(s)->flags = (f); CHAIN_NODE(s)->pkts = (p); \ +- CHAIN_NODE(s)->bytes = (b);}) +-#define PKTCCLRATTR(s) ({CHAIN_NODE(s)->flags = CHAIN_NODE(s)->pkts = \ +- CHAIN_NODE(s)->bytes = 0;}) +-#define PKTCGETATTR(s) (CHAIN_NODE(s)->flags << 29 | CHAIN_NODE(s)->pkts << 20 | \ +- CHAIN_NODE(s)->bytes) + #define PKTCCNT(skb) (CHAIN_NODE(skb)->pkts) + #define PKTCLEN(skb) (CHAIN_NODE(skb)->bytes) +-#define PKTCGETFLAGS(skb) (CHAIN_NODE(skb)->flags) +-#define PKTCSETFLAGS(skb, f) (CHAIN_NODE(skb)->flags = (f)) +-#define PKTCCLRFLAGS(skb) (CHAIN_NODE(skb)->flags = 0) + #define PKTCFLAGS(skb) (CHAIN_NODE(skb)->flags) +-#define PKTCSETCNT(skb, c) (CHAIN_NODE(skb)->pkts = (c)) +-#define PKTCINCRCNT(skb) (CHAIN_NODE(skb)->pkts++) +-#define PKTCADDCNT(skb, c) (CHAIN_NODE(skb)->pkts += (c)) +-#define PKTCSETLEN(skb, l) (CHAIN_NODE(skb)->bytes = (l)) +-#define PKTCADDLEN(skb, l) (CHAIN_NODE(skb)->bytes += (l)) ++#define PKTCSETCNT(skb, c) (CHAIN_NODE(skb)->pkts = (c) & ((1 << 9) - 1)) ++#define PKTCSETLEN(skb, l) (CHAIN_NODE(skb)->bytes = (l) & ((1 << 20) - 1)) + #define PKTCSETFLAG(skb, fb) (CHAIN_NODE(skb)->flags |= (fb)) + #define PKTCCLRFLAG(skb, fb) (CHAIN_NODE(skb)->flags &= ~(fb)) + #define PKTCLINK(skb) (CHAIN_NODE(skb)->link) + #define PKTSETCLINK(skb, x) (CHAIN_NODE(skb)->link = (struct sk_buff*)(x)) ++#define PKTISCHAINED(skb) (PKTCLINK(skb) != NULL) + #define FOREACH_CHAINED_PKT(skb, nskb) \ + for (; (skb) != NULL; (skb) = (nskb)) \ +- if ((nskb) = (PKTISCHAINED(skb) ? PKTCLINK(skb) : NULL), \ +- PKTSETCLINK((skb), NULL), 1) ++ if ((nskb) = PKTCLINK(skb), PKTSETCLINK((skb), NULL), 1) + #define PKTCFREE(osh, skb, send) \ + do { \ + void *nskb; \ + ASSERT((skb) != NULL); \ + FOREACH_CHAINED_PKT((skb), nskb) { \ +- PKTCLRCHAINED((osh), (skb)); \ +- PKTCCLRFLAGS((skb)); \ + PKTFREE((osh), (skb), (send)); \ + } \ + } while (0) +-#define PKTCENQTAIL(h, t, p) \ +-do { \ +- if ((t) == NULL) { \ +- (h) = (t) = (p); \ +- } else { \ +- PKTSETCLINK((t), (p)); \ +- (t) = (p); \ +- } \ +-} while (0) + #endif /* PKTC */ + + #else /* ! BCMDRIVER */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/linuxver.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/linuxver.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/linuxver.h 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/linuxver.h 2014-02-15 00:43:44.795014136 +0100 +@@ -2,7 +2,7 @@ + * Linux-specific abstractions to gain some independence from linux kernel versions. + * Pave over some 2.2 versus 2.4 versus 2.6 kernel differences. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -22,13 +22,12 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: linuxver.h 417757 2013-08-12 12:24:45Z $ ++ * $Id: linuxver.h 366812 2012-11-05 13:49:32Z $ + */ + + #ifndef _linuxver_h_ + #define _linuxver_h_ + +-#include + #include + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) + #include +@@ -69,7 +68,6 @@ + #include + #include + #include +-#include + #include + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) + #include +@@ -99,10 +97,7 @@ + #endif + #endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 41) */ + +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) +-#define DAEMONIZE(a) +-#elif ((LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) && \ +- (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) + #define DAEMONIZE(a) daemonize(a); \ + allow_signal(SIGKILL); \ + allow_signal(SIGTERM); +@@ -155,11 +150,7 @@ typedef irqreturn_t(*FN_ISR) (int irq, v + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) + #include +-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) */ +- +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)) +-#include +-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */ ++#endif + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) + #include +@@ -173,6 +164,7 @@ typedef irqreturn_t(*FN_ISR) (int irq, v + #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) */ + + ++ + #ifndef __exit + #define __exit + #endif +@@ -496,11 +488,9 @@ pci_restore_state(struct pci_dev *dev, u + #define SET_NETDEV_DEV(net, pdev) do {} while (0) + #endif + +-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)) + #ifndef HAVE_FREE_NETDEV + #define free_netdev(dev) kfree(dev) + #endif +-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0) */ + + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) + /* struct packet_type redefined in 2.6.x */ +@@ -519,16 +509,13 @@ pci_restore_state(struct pci_dev *dev, u + #endif + + typedef struct { +- void *parent; /* some external entity that the thread supposed to work for */ +- char *proc_name; ++ void *parent; /* some external entity that the thread supposed to work for */ + struct task_struct *p_task; +- long thr_pid; +- int prio; /* priority */ ++ long thr_pid; ++ int prio; /* priority */ + struct semaphore sema; + int terminated; + struct completion completed; +- spinlock_t spinlock; +- int up_cnt; + } tsk_ctl_t; + + +@@ -540,63 +527,38 @@ typedef struct { + #define DBG_THR(x) + #endif + +-static inline bool binary_sema_down(tsk_ctl_t *tsk) +-{ +- if (down_interruptible(&tsk->sema) == 0) { +- unsigned long flags = 0; +- spin_lock_irqsave(&tsk->spinlock, flags); +- if (tsk->up_cnt == 1) +- tsk->up_cnt--; +- else { +- DBG_THR(("dhd_dpc_thread: Unexpected up_cnt %d\n", tsk->up_cnt)); +- } +- spin_unlock_irqrestore(&tsk->spinlock, flags); +- return FALSE; +- } else +- return TRUE; +-} +- +-static inline bool binary_sema_up(tsk_ctl_t *tsk) +-{ +- bool sem_up = FALSE; +- unsigned long flags = 0; +- +- spin_lock_irqsave(&tsk->spinlock, flags); +- if (tsk->up_cnt == 0) { +- tsk->up_cnt++; +- sem_up = TRUE; +- } else if (tsk->up_cnt == 1) { +- /* dhd_sched_dpc: dpc is alread up! */ +- } else +- DBG_THR(("dhd_sched_dpc: unexpected up cnt %d!\n", tsk->up_cnt)); +- +- spin_unlock_irqrestore(&tsk->spinlock, flags); +- +- if (sem_up) +- up(&tsk->sema); +- +- return sem_up; +-} +- + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) + #define SMP_RD_BARRIER_DEPENDS(x) smp_read_barrier_depends(x) + #else + #define SMP_RD_BARRIER_DEPENDS(x) smp_rmb(x) + #endif + +-#define PROC_START(thread_func, owner, tsk_ctl, flags, name) \ ++ ++#define PROC_START(thread_func, owner, tsk_ctl, flags) \ ++{ \ ++ sema_init(&((tsk_ctl)->sema), 0); \ ++ init_completion(&((tsk_ctl)->completed)); \ ++ (tsk_ctl)->parent = owner; \ ++ (tsk_ctl)->terminated = FALSE; \ ++ (tsk_ctl)->thr_pid = kernel_thread(thread_func, tsk_ctl, flags); \ ++ DBG_THR(("%s thr:%lx created\n", __FUNCTION__, (tsk_ctl)->thr_pid)); \ ++ if ((tsk_ctl)->thr_pid > 0) \ ++ wait_for_completion(&((tsk_ctl)->completed)); \ ++ DBG_THR(("%s thr:%lx started\n", __FUNCTION__, (tsk_ctl)->thr_pid)); \ ++} ++ ++#ifdef USE_KTHREAD_API ++#define PROC_START2(thread_func, owner, tsk_ctl, flags, name) \ + { \ + sema_init(&((tsk_ctl)->sema), 0); \ + init_completion(&((tsk_ctl)->completed)); \ + (tsk_ctl)->parent = owner; \ +- (tsk_ctl)->proc_name = name; \ + (tsk_ctl)->terminated = FALSE; \ + (tsk_ctl)->p_task = kthread_run(thread_func, tsk_ctl, (char*)name); \ + (tsk_ctl)->thr_pid = (tsk_ctl)->p_task->pid; \ +- spin_lock_init(&((tsk_ctl)->spinlock)); \ +- DBG_THR(("%s(): thread:%s:%lx started\n", __FUNCTION__, \ +- (tsk_ctl)->proc_name, (tsk_ctl)->thr_pid)); \ ++ DBG_THR(("%s thr:%lx created\n", __FUNCTION__, (tsk_ctl)->thr_pid)); \ + } ++#endif + + #define PROC_STOP(tsk_ctl) \ + { \ +@@ -604,8 +566,7 @@ static inline bool binary_sema_up(tsk_ct + smp_wmb(); \ + up(&((tsk_ctl)->sema)); \ + wait_for_completion(&((tsk_ctl)->completed)); \ +- DBG_THR(("%s(): thread:%s:%lx terminated OK\n", __FUNCTION__, \ +- (tsk_ctl)->proc_name, (tsk_ctl)->thr_pid)); \ ++ DBG_THR(("%s thr:%lx terminated OK\n", __FUNCTION__, (tsk_ctl)->thr_pid)); \ + (tsk_ctl)->thr_pid = -1; \ + } + +@@ -698,16 +659,4 @@ not match our unaligned address for < 2. + #define netdev_priv(dev) dev->priv + #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) */ + +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) +-#define RANDOM32 prandom_u32 +-#else +-#define RANDOM32 random32 +-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) */ +- +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) +-#define SRANDOM32(entropy) prandom_seed(entropy) +-#else +-#define SRANDOM32(entropy) srandom32(entropy) +-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) */ +- + #endif /* _linuxver_h_ */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/Makefile linux-sunxi-new/drivers/net/wireless/bcmdhd/include/Makefile +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/Makefile 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/Makefile 2014-02-15 00:43:44.794014114 +0100 +@@ -10,10 +10,10 @@ + # + # Copyright 2005, Broadcom, Inc. + # +-# $Id: Makefile 347587 2012-07-27 09:13:31Z prakashd $ ++# $Id: Makefile 241686 2011-02-19 00:22:45Z prakashd $ + # + +-export SRCBASE:=.. ++SRCBASE := .. + + TARGETS := epivers.h + +@@ -23,11 +23,11 @@ endif + + all release: epivers compvers + +-# Generate epivers.h for native branch url ++# Generate epivers.h for native branch version + epivers: + bash epivers.sh + +-# Generate component versions based on component url ++# Generate epivers.h for native branch version + compvers: + @if [ -s "compvers.sh" ]; then \ + echo "Generating component versions, if any"; \ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/miniopt.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/miniopt.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/miniopt.h 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/miniopt.h 2014-02-15 00:43:44.794014114 +0100 +@@ -1,7 +1,7 @@ + /* + * Command line options parser. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/msgtrace.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/msgtrace.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/msgtrace.h 2014-01-27 01:30:30.101433269 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/msgtrace.h 2014-02-15 00:43:44.793014092 +0100 +@@ -1,7 +1,7 @@ + /* + * Trace messages sent over HBUS + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -21,7 +21,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: msgtrace.h 369735 2012-11-19 22:50:22Z $ ++ * $Id: msgtrace.h 281527 2011-09-02 17:12:53Z $ + */ + + #ifndef _MSGTRACE_H +@@ -40,14 +40,11 @@ + /* Message trace header */ + typedef BWL_PRE_PACKED_STRUCT struct msgtrace_hdr { + uint8 version; +- uint8 trace_type; +-#define MSGTRACE_HDR_TYPE_MSG 0 +-#define MSGTRACE_HDR_TYPE_LOG 1 ++ uint8 spare; + uint16 len; /* Len of the trace */ + uint32 seqnum; /* Sequence number of message. Useful if the messsage has been lost + * because of DMA error or a bus reset (ex: SDIO Func2) + */ +- /* Msgtrace type only */ + uint32 discarded_bytes; /* Number of discarded bytes because of trace overflow */ + uint32 discarded_printf; /* Number of discarded printf because of trace overflow */ + } BWL_POST_PACKED_STRUCT msgtrace_hdr_t; +@@ -66,7 +63,7 @@ typedef void (*msgtrace_func_send_t)(voi + uint16 hdrlen, uint8 *buf, uint16 buflen); + extern void msgtrace_start(void); + extern void msgtrace_stop(void); +-extern int msgtrace_sent(void); ++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); + extern bool msgtrace_event_enabled(void); +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/osl.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/osl.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/osl.h 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/osl.h 2014-02-15 00:43:44.794014114 +0100 +@@ -1,7 +1,7 @@ + /* + * OS Abstraction Layer + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -21,7 +21,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: osl.h 370064 2012-11-20 21:00:25Z $ ++ * $Id: osl.h 320905 2012-03-13 15:33:25Z $ + */ + + #ifndef _osl_h_ +@@ -71,33 +71,20 @@ typedef void (*osl_wreg_fn_t)(void *ctx + #endif /* OSL_SYSUPTIME */ + + #if !defined(PKTC) +-#define PKTCGETATTR(s) (0) +-#define PKTCSETATTR(skb, f, p, b) +-#define PKTCCLRATTR(skb) +-#define PKTCCNT(skb) (1) +-#define PKTCLEN(skb) PKTLEN(NULL, skb) +-#define PKTCGETFLAGS(skb) (0) +-#define PKTCSETFLAGS(skb, f) +-#define PKTCCLRFLAGS(skb) ++#define PKTCCNT(skb) (0) ++#define PKTCLEN(skb) (0) + #define PKTCFLAGS(skb) (0) + #define PKTCSETCNT(skb, c) +-#define PKTCINCRCNT(skb) +-#define PKTCADDCNT(skb, c) + #define PKTCSETLEN(skb, l) +-#define PKTCADDLEN(skb, l) + #define PKTCSETFLAG(skb, fb) + #define PKTCCLRFLAG(skb, fb) +-#define PKTCLINK(skb) NULL +-#define PKTSETCLINK(skb, x) ++#define PKTCLINK(skb) PKTLINK(skb) ++#define PKTSETCLINK(skb, x) PKTSETLINK((skb), (x)) ++#define PKTISCHAINED(skb) FALSE + #define FOREACH_CHAINED_PKT(skb, nskb) \ + for ((nskb) = NULL; (skb) != NULL; (skb) = (nskb)) + #define PKTCFREE PKTFREE +-#endif /* !linux || !PKTC */ +- +-#ifndef HNDCTF +-#define PKTSETCHAINED(osh, skb) +-#define PKTCLRCHAINED(osh, skb) +-#define PKTISCHAINED(skb) (FALSE) + #endif + ++ + #endif /* _osl_h_ */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/packed_section_end.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/packed_section_end.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/packed_section_end.h 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/packed_section_end.h 2014-02-15 00:43:44.794014114 +0100 +@@ -15,7 +15,7 @@ + * #include + * + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/packed_section_start.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/packed_section_start.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/packed_section_start.h 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/packed_section_start.h 2014-02-15 00:43:44.794014114 +0100 +@@ -15,7 +15,7 @@ + * #include + * + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/pcicfg.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/pcicfg.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/pcicfg.h 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/pcicfg.h 2014-02-15 00:43:44.794014114 +0100 +@@ -1,7 +1,7 @@ + /* + * pcicfg.h: PCI configuration constants and structures. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -21,7 +21,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: pcicfg.h 346935 2012-07-25 00:24:55Z $ ++ * $Id: pcicfg.h 309193 2012-01-19 00:03:57Z $ + */ + + #ifndef _h_pcicfg_ +@@ -58,7 +58,6 @@ + #define PCI_CFG_PIN 0x3d + #define PCI_CFG_MINGNT 0x3e + #define PCI_CFG_MAXLAT 0x3f +-#define PCI_CFG_DEVCTRL 0xd8 + #define PCI_BAR0_WIN 0x80 /* backplane addres space accessed by BAR0 */ + #define PCI_BAR1_WIN 0x84 /* backplane addres space accessed by BAR1 */ + #define PCI_SPROM_CONTROL 0x88 /* sprom property control */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/proto/802.11_bta.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/proto/802.11_bta.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/proto/802.11_bta.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/proto/802.11_bta.h 2014-02-15 00:43:44.793014092 +0100 +@@ -0,0 +1,45 @@ ++/* ++ * BT-AMP (BlueTooth Alternate Mac and Phy) 802.11 PAL (Protocol Adaptation Layer) ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: 802.11_bta.h 294267 2011-11-04 23:41:52Z $ ++*/ ++ ++#ifndef _802_11_BTA_H_ ++#define _802_11_BTA_H_ ++ ++#define BT_SIG_SNAP_MPROT "\xAA\xAA\x03\x00\x19\x58" ++ ++/* BT-AMP 802.11 PAL Protocols */ ++#define BTA_PROT_L2CAP 1 ++#define BTA_PROT_ACTIVITY_REPORT 2 ++#define BTA_PROT_SECURITY 3 ++#define BTA_PROT_LINK_SUPERVISION_REQUEST 4 ++#define BTA_PROT_LINK_SUPERVISION_REPLY 5 ++ ++/* BT-AMP 802.11 PAL AMP_ASSOC Type IDs */ ++#define BTA_TYPE_ID_MAC_ADDRESS 1 ++#define BTA_TYPE_ID_PREFERRED_CHANNELS 2 ++#define BTA_TYPE_ID_CONNECTED_CHANNELS 3 ++#define BTA_TYPE_ID_CAPABILITIES 4 ++#define BTA_TYPE_ID_VERSION 5 ++#endif /* _802_11_bta_h_ */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/proto/802.11e.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/proto/802.11e.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/proto/802.11e.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/proto/802.11e.h 2014-02-15 00:43:44.793014092 +0100 +@@ -0,0 +1,131 @@ ++/* ++ * 802.11e protocol header file ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: 802.11e.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _802_11e_H_ ++#define _802_11e_H_ ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++ ++/* WME Traffic Specification (TSPEC) element */ ++#define WME_TSPEC_HDR_LEN 2 /* WME TSPEC header length */ ++#define WME_TSPEC_BODY_OFF 2 /* WME TSPEC body offset */ ++ ++#define WME_CATEGORY_CODE_OFFSET 0 /* WME Category code offset */ ++#define WME_ACTION_CODE_OFFSET 1 /* WME Action code offset */ ++#define WME_TOKEN_CODE_OFFSET 2 /* WME Token code offset */ ++#define WME_STATUS_CODE_OFFSET 3 /* WME Status code offset */ ++ ++BWL_PRE_PACKED_STRUCT struct tsinfo { ++ uint8 octets[3]; ++} BWL_POST_PACKED_STRUCT; ++ ++typedef struct tsinfo tsinfo_t; ++ ++/* 802.11e TSPEC IE */ ++typedef BWL_PRE_PACKED_STRUCT struct tspec { ++ uint8 oui[DOT11_OUI_LEN]; /* WME_OUI */ ++ uint8 type; /* WME_TYPE */ ++ uint8 subtype; /* WME_SUBTYPE_TSPEC */ ++ uint8 version; /* WME_VERSION */ ++ tsinfo_t tsinfo; /* TS Info bit field */ ++ uint16 nom_msdu_size; /* (Nominal or fixed) MSDU Size (bytes) */ ++ uint16 max_msdu_size; /* Maximum MSDU Size (bytes) */ ++ uint32 min_srv_interval; /* Minimum Service Interval (us) */ ++ uint32 max_srv_interval; /* Maximum Service Interval (us) */ ++ uint32 inactivity_interval; /* Inactivity Interval (us) */ ++ uint32 suspension_interval; /* Suspension Interval (us) */ ++ uint32 srv_start_time; /* Service Start Time (us) */ ++ uint32 min_data_rate; /* Minimum Data Rate (bps) */ ++ uint32 mean_data_rate; /* Mean Data Rate (bps) */ ++ uint32 peak_data_rate; /* Peak Data Rate (bps) */ ++ uint32 max_burst_size; /* Maximum Burst Size (bytes) */ ++ uint32 delay_bound; /* Delay Bound (us) */ ++ uint32 min_phy_rate; /* Minimum PHY Rate (bps) */ ++ uint16 surplus_bw; /* Surplus Bandwidth Allowance (range 1.0-8.0) */ ++ uint16 medium_time; /* Medium Time (32 us/s periods) */ ++} BWL_POST_PACKED_STRUCT tspec_t; ++ ++#define WME_TSPEC_LEN (sizeof(tspec_t)) /* not including 2-bytes of header */ ++ ++/* ts_info */ ++/* 802.1D priority is duplicated - bits 13-11 AND bits 3-1 */ ++#define TS_INFO_TID_SHIFT 1 /* TS info. TID shift */ ++#define TS_INFO_TID_MASK (0xf << TS_INFO_TID_SHIFT) /* TS info. TID mask */ ++#define TS_INFO_CONTENTION_SHIFT 7 /* TS info. contention shift */ ++#define TS_INFO_CONTENTION_MASK (0x1 << TS_INFO_CONTENTION_SHIFT) /* TS info. contention mask */ ++#define TS_INFO_DIRECTION_SHIFT 5 /* TS info. direction shift */ ++#define TS_INFO_DIRECTION_MASK (0x3 << TS_INFO_DIRECTION_SHIFT) /* TS info. direction mask */ ++#define TS_INFO_PSB_SHIFT 2 /* TS info. PSB bit Shift */ ++#define TS_INFO_PSB_MASK (1 << TS_INFO_PSB_SHIFT) /* TS info. PSB mask */ ++#define TS_INFO_UPLINK (0 << TS_INFO_DIRECTION_SHIFT) /* TS info. uplink */ ++#define TS_INFO_DOWNLINK (1 << TS_INFO_DIRECTION_SHIFT) /* TS info. downlink */ ++#define TS_INFO_BIDIRECTIONAL (3 << TS_INFO_DIRECTION_SHIFT) /* TS info. bidirectional */ ++#define TS_INFO_USER_PRIO_SHIFT 3 /* TS info. user priority shift */ ++/* TS info. user priority mask */ ++#define TS_INFO_USER_PRIO_MASK (0x7 << TS_INFO_USER_PRIO_SHIFT) ++ ++/* Macro to get/set bit(s) field in TSINFO */ ++#define WLC_CAC_GET_TID(pt) ((((pt).octets[0]) & TS_INFO_TID_MASK) >> TS_INFO_TID_SHIFT) ++#define WLC_CAC_GET_DIR(pt) ((((pt).octets[0]) & \ ++ TS_INFO_DIRECTION_MASK) >> TS_INFO_DIRECTION_SHIFT) ++#define WLC_CAC_GET_PSB(pt) ((((pt).octets[1]) & TS_INFO_PSB_MASK) >> TS_INFO_PSB_SHIFT) ++#define WLC_CAC_GET_USER_PRIO(pt) ((((pt).octets[1]) & \ ++ TS_INFO_USER_PRIO_MASK) >> TS_INFO_USER_PRIO_SHIFT) ++ ++#define WLC_CAC_SET_TID(pt, id) ((((pt).octets[0]) & (~TS_INFO_TID_MASK)) | \ ++ ((id) << TS_INFO_TID_SHIFT)) ++#define WLC_CAC_SET_USER_PRIO(pt, prio) ((((pt).octets[0]) & (~TS_INFO_USER_PRIO_MASK)) | \ ++ ((prio) << TS_INFO_USER_PRIO_SHIFT)) ++ ++/* 802.11e QBSS Load IE */ ++#define QBSS_LOAD_IE_LEN 5 /* QBSS Load IE length */ ++#define QBSS_LOAD_AAC_OFF 3 /* AAC offset in IE */ ++ ++#define CAC_ADDTS_RESP_TIMEOUT 300 /* default ADDTS response timeout in ms */ ++ ++/* 802.11e ADDTS status code */ ++#define DOT11E_STATUS_ADMISSION_ACCEPTED 0 /* TSPEC Admission accepted status */ ++#define DOT11E_STATUS_ADDTS_INVALID_PARAM 1 /* TSPEC invalid parameter status */ ++#define DOT11E_STATUS_ADDTS_REFUSED_NSBW 3 /* ADDTS refused (non-sufficient BW) */ ++#define DOT11E_STATUS_ADDTS_REFUSED_AWHILE 47 /* ADDTS refused but could retry later */ ++ ++/* 802.11e DELTS status code */ ++#define DOT11E_STATUS_QSTA_LEAVE_QBSS 36 /* STA leave QBSS */ ++#define DOT11E_STATUS_END_TS 37 /* END TS */ ++#define DOT11E_STATUS_UNKNOWN_TS 38 /* UNKNOWN TS */ ++#define DOT11E_STATUS_QSTA_REQ_TIMEOUT 39 /* STA ADDTS request timeout */ ++ ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _802_11e_CAC_H_ */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/proto/802.11.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/proto/802.11.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/proto/802.11.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/proto/802.11.h 2014-02-15 00:43:44.793014092 +0100 +@@ -0,0 +1,2355 @@ ++/* ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * Fundamental types and constants relating to 802.11 ++ * ++ * $Id: 802.11.h 346820 2012-07-24 13:53:12Z $ ++ */ ++ ++#ifndef _802_11_H_ ++#define _802_11_H_ ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++ ++#ifndef _NET_ETHERNET_H_ ++#include ++#endif ++ ++#include ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++ ++#define DOT11_TU_TO_US 1024 /* 802.11 Time Unit is 1024 microseconds */ ++ ++/* Generic 802.11 frame constants */ ++#define DOT11_A3_HDR_LEN 24 /* d11 header length with A3 */ ++#define DOT11_A4_HDR_LEN 30 /* d11 header length with A4 */ ++#define DOT11_MAC_HDR_LEN DOT11_A3_HDR_LEN /* MAC header length */ ++#define DOT11_FCS_LEN 4 /* d11 FCS length */ ++#define DOT11_ICV_LEN 4 /* d11 ICV length */ ++#define DOT11_ICV_AES_LEN 8 /* d11 ICV/AES length */ ++#define DOT11_QOS_LEN 2 /* d11 QoS length */ ++#define DOT11_HTC_LEN 4 /* d11 HT Control field length */ ++ ++#define DOT11_KEY_INDEX_SHIFT 6 /* d11 key index shift */ ++#define DOT11_IV_LEN 4 /* d11 IV length */ ++#define DOT11_IV_TKIP_LEN 8 /* d11 IV TKIP length */ ++#define DOT11_IV_AES_OCB_LEN 4 /* d11 IV/AES/OCB length */ ++#define DOT11_IV_AES_CCM_LEN 8 /* d11 IV/AES/CCM length */ ++#define DOT11_IV_MAX_LEN 8 /* maximum iv len for any encryption */ ++ ++/* Includes MIC */ ++#define DOT11_MAX_MPDU_BODY_LEN 2304 /* max MPDU body length */ ++/* A4 header + QoS + CCMP + PDU + ICV + FCS = 2352 */ ++#define DOT11_MAX_MPDU_LEN (DOT11_A4_HDR_LEN + \ ++ DOT11_QOS_LEN + \ ++ DOT11_IV_AES_CCM_LEN + \ ++ DOT11_MAX_MPDU_BODY_LEN + \ ++ DOT11_ICV_LEN + \ ++ DOT11_FCS_LEN) /* d11 max MPDU length */ ++ ++#define DOT11_MAX_SSID_LEN 32 /* d11 max ssid length */ ++ ++/* dot11RTSThreshold */ ++#define DOT11_DEFAULT_RTS_LEN 2347 /* d11 default RTS length */ ++#define DOT11_MAX_RTS_LEN 2347 /* d11 max RTS length */ ++ ++/* dot11FragmentationThreshold */ ++#define DOT11_MIN_FRAG_LEN 256 /* d11 min fragmentation length */ ++#define DOT11_MAX_FRAG_LEN 2346 /* Max frag is also limited by aMPDUMaxLength ++ * of the attached PHY ++ */ ++#define DOT11_DEFAULT_FRAG_LEN 2346 /* d11 default fragmentation length */ ++ ++/* dot11BeaconPeriod */ ++#define DOT11_MIN_BEACON_PERIOD 1 /* d11 min beacon period */ ++#define DOT11_MAX_BEACON_PERIOD 0xFFFF /* d11 max beacon period */ ++ ++/* dot11DTIMPeriod */ ++#define DOT11_MIN_DTIM_PERIOD 1 /* d11 min DTIM period */ ++#define DOT11_MAX_DTIM_PERIOD 0xFF /* d11 max DTIM period */ ++ ++/* 802.2 LLC/SNAP header used by 802.11 per 802.1H */ ++#define DOT11_LLC_SNAP_HDR_LEN 8 /* d11 LLC/SNAP header length */ ++#define DOT11_OUI_LEN 3 /* d11 OUI length */ ++BWL_PRE_PACKED_STRUCT struct dot11_llc_snap_header { ++ uint8 dsap; /* always 0xAA */ ++ uint8 ssap; /* always 0xAA */ ++ uint8 ctl; /* always 0x03 */ ++ uint8 oui[DOT11_OUI_LEN]; /* RFC1042: 0x00 0x00 0x00 ++ * Bridge-Tunnel: 0x00 0x00 0xF8 ++ */ ++ uint16 type; /* ethertype */ ++} BWL_POST_PACKED_STRUCT; ++ ++/* RFC1042 header used by 802.11 per 802.1H */ ++#define RFC1042_HDR_LEN (ETHER_HDR_LEN + DOT11_LLC_SNAP_HDR_LEN) /* RCF1042 header length */ ++ ++/* Generic 802.11 MAC header */ ++/* ++ * N.B.: This struct reflects the full 4 address 802.11 MAC header. ++ * The fields are defined such that the shorter 1, 2, and 3 ++ * address headers just use the first k fields. ++ */ ++BWL_PRE_PACKED_STRUCT struct dot11_header { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* duration/ID */ ++ struct ether_addr a1; /* address 1 */ ++ struct ether_addr a2; /* address 2 */ ++ struct ether_addr a3; /* address 3 */ ++ uint16 seq; /* sequence control */ ++ struct ether_addr a4; /* address 4 */ ++} BWL_POST_PACKED_STRUCT; ++ ++/* Control frames */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_rts_frame { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* duration/ID */ ++ struct ether_addr ra; /* receiver address */ ++ struct ether_addr ta; /* transmitter address */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_RTS_LEN 16 /* d11 RTS frame length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_cts_frame { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* duration/ID */ ++ struct ether_addr ra; /* receiver address */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_CTS_LEN 10 /* d11 CTS frame length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_ack_frame { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* duration/ID */ ++ struct ether_addr ra; /* receiver address */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_ACK_LEN 10 /* d11 ACK frame length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_ps_poll_frame { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* AID */ ++ struct ether_addr bssid; /* receiver address, STA in AP */ ++ struct ether_addr ta; /* transmitter address */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_PS_POLL_LEN 16 /* d11 PS poll frame length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_cf_end_frame { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* duration/ID */ ++ struct ether_addr ra; /* receiver address */ ++ struct ether_addr bssid; /* transmitter address, STA in AP */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_CS_END_LEN 16 /* d11 CF-END frame length */ ++ ++/* RWL wifi protocol: The Vendor Specific Action frame is defined for vendor-specific signaling ++* category+OUI+vendor specific content ( this can be variable) ++*/ ++BWL_PRE_PACKED_STRUCT struct dot11_action_wifi_vendor_specific { ++ uint8 category; ++ uint8 OUI[3]; ++ uint8 type; ++ uint8 subtype; ++ uint8 data[1040]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_action_wifi_vendor_specific dot11_action_wifi_vendor_specific_t; ++ ++/* generic vender specific action frame with variable length */ ++BWL_PRE_PACKED_STRUCT struct dot11_action_vs_frmhdr { ++ uint8 category; ++ uint8 OUI[3]; ++ uint8 type; ++ uint8 subtype; ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_action_vs_frmhdr dot11_action_vs_frmhdr_t; ++#define DOT11_ACTION_VS_HDR_LEN 6 ++ ++#define BCM_ACTION_OUI_BYTE0 0x00 ++#define BCM_ACTION_OUI_BYTE1 0x90 ++#define BCM_ACTION_OUI_BYTE2 0x4c ++ ++/* BA/BAR Control parameters */ ++#define DOT11_BA_CTL_POLICY_NORMAL 0x0000 /* normal ack */ ++#define DOT11_BA_CTL_POLICY_NOACK 0x0001 /* no ack */ ++#define DOT11_BA_CTL_POLICY_MASK 0x0001 /* ack policy mask */ ++ ++#define DOT11_BA_CTL_MTID 0x0002 /* multi tid BA */ ++#define DOT11_BA_CTL_COMPRESSED 0x0004 /* compressed bitmap */ ++ ++#define DOT11_BA_CTL_NUMMSDU_MASK 0x0FC0 /* num msdu in bitmap mask */ ++#define DOT11_BA_CTL_NUMMSDU_SHIFT 6 /* num msdu in bitmap shift */ ++ ++#define DOT11_BA_CTL_TID_MASK 0xF000 /* tid mask */ ++#define DOT11_BA_CTL_TID_SHIFT 12 /* tid shift */ ++ ++/* control frame header (BA/BAR) */ ++BWL_PRE_PACKED_STRUCT struct dot11_ctl_header { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* duration/ID */ ++ struct ether_addr ra; /* receiver address */ ++ struct ether_addr ta; /* transmitter address */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_CTL_HDR_LEN 16 /* control frame hdr len */ ++ ++/* BAR frame payload */ ++BWL_PRE_PACKED_STRUCT struct dot11_bar { ++ uint16 bar_control; /* BAR Control */ ++ uint16 seqnum; /* Starting Sequence control */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_BAR_LEN 4 /* BAR frame payload length */ ++ ++#define DOT11_BA_BITMAP_LEN 128 /* bitmap length */ ++#define DOT11_BA_CMP_BITMAP_LEN 8 /* compressed bitmap length */ ++/* BA frame payload */ ++BWL_PRE_PACKED_STRUCT struct dot11_ba { ++ uint16 ba_control; /* BA Control */ ++ uint16 seqnum; /* Starting Sequence control */ ++ uint8 bitmap[DOT11_BA_BITMAP_LEN]; /* Block Ack Bitmap */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_BA_LEN 4 /* BA frame payload len (wo bitmap) */ ++ ++/* Management frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_management_header { ++ uint16 fc; /* frame control */ ++ uint16 durid; /* duration/ID */ ++ struct ether_addr da; /* receiver address */ ++ struct ether_addr sa; /* transmitter address */ ++ struct ether_addr bssid; /* BSS ID */ ++ uint16 seq; /* sequence control */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_MGMT_HDR_LEN 24 /* d11 management header length */ ++ ++/* Management frame payloads */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_bcn_prb { ++ uint32 timestamp[2]; ++ uint16 beacon_interval; ++ uint16 capability; ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_BCN_PRB_LEN 12 /* 802.11 beacon/probe frame fixed length */ ++#define DOT11_BCN_PRB_FIXED_LEN 12 /* 802.11 beacon/probe frame fixed length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_auth { ++ uint16 alg; /* algorithm */ ++ uint16 seq; /* sequence control */ ++ uint16 status; /* status code */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_AUTH_FIXED_LEN 6 /* length of auth frame without challenge IE */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_assoc_req { ++ uint16 capability; /* capability information */ ++ uint16 listen; /* listen interval */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_ASSOC_REQ_FIXED_LEN 4 /* length of assoc frame without info elts */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_reassoc_req { ++ uint16 capability; /* capability information */ ++ uint16 listen; /* listen interval */ ++ struct ether_addr ap; /* Current AP address */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_REASSOC_REQ_FIXED_LEN 10 /* length of assoc frame without info elts */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_assoc_resp { ++ uint16 capability; /* capability information */ ++ uint16 status; /* status code */ ++ uint16 aid; /* association ID */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_ASSOC_RESP_FIXED_LEN 6 /* length of assoc resp frame without info elts */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_action_measure { ++ uint8 category; ++ uint8 action; ++ uint8 token; ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_ACTION_MEASURE_LEN 3 /* d11 action measurement header length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_action_ht_ch_width { ++ uint8 category; ++ uint8 action; ++ uint8 ch_width; ++} BWL_POST_PACKED_STRUCT; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_action_ht_mimops { ++ uint8 category; ++ uint8 action; ++ uint8 control; ++} BWL_POST_PACKED_STRUCT; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_action_sa_query { ++ uint8 category; ++ uint8 action; ++ uint16 id; ++} BWL_POST_PACKED_STRUCT; ++ ++#define SM_PWRSAVE_ENABLE 1 ++#define SM_PWRSAVE_MODE 2 ++ ++/* ************* 802.11h related definitions. ************* */ ++BWL_PRE_PACKED_STRUCT struct dot11_power_cnst { ++ uint8 id; ++ uint8 len; ++ uint8 power; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_power_cnst dot11_power_cnst_t; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_power_cap { ++ uint8 min; ++ uint8 max; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_power_cap dot11_power_cap_t; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_tpc_rep { ++ uint8 id; ++ uint8 len; ++ uint8 tx_pwr; ++ uint8 margin; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_tpc_rep dot11_tpc_rep_t; ++#define DOT11_MNG_IE_TPC_REPORT_LEN 2 /* length of IE data, not including 2 byte header */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_supp_channels { ++ uint8 id; ++ uint8 len; ++ uint8 first_channel; ++ uint8 num_channels; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_supp_channels dot11_supp_channels_t; ++ ++/* Extension Channel Offset IE: 802.11n-D1.0 spec. added sideband ++ * offset for 40MHz operation. The possible 3 values are: ++ * 1 = above control channel ++ * 3 = below control channel ++ * 0 = no extension channel ++ */ ++BWL_PRE_PACKED_STRUCT struct dot11_extch { ++ uint8 id; /* IE ID, 62, DOT11_MNG_EXT_CHANNEL_OFFSET */ ++ uint8 len; /* IE length */ ++ uint8 extch; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_extch dot11_extch_ie_t; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_brcm_extch { ++ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */ ++ uint8 len; /* IE length */ ++ uint8 oui[3]; /* Proprietary OUI, BRCM_PROP_OUI */ ++ uint8 type; /* type inidicates what follows */ ++ uint8 extch; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_brcm_extch dot11_brcm_extch_ie_t; ++ ++#define BRCM_EXTCH_IE_LEN 5 ++#define BRCM_EXTCH_IE_TYPE 53 /* 802.11n ID not yet assigned */ ++#define DOT11_EXTCH_IE_LEN 1 ++#define DOT11_EXT_CH_MASK 0x03 /* extension channel mask */ ++#define DOT11_EXT_CH_UPPER 0x01 /* ext. ch. on upper sb */ ++#define DOT11_EXT_CH_LOWER 0x03 /* ext. ch. on lower sb */ ++#define DOT11_EXT_CH_NONE 0x00 /* no extension ch. */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_action_frmhdr { ++ uint8 category; ++ uint8 action; ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_ACTION_FRMHDR_LEN 2 ++ ++/* CSA IE data structure */ ++BWL_PRE_PACKED_STRUCT struct dot11_channel_switch { ++ uint8 id; /* id DOT11_MNG_CHANNEL_SWITCH_ID */ ++ uint8 len; /* length of IE */ ++ uint8 mode; /* mode 0 or 1 */ ++ uint8 channel; /* channel switch to */ ++ uint8 count; /* number of beacons before switching */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_channel_switch dot11_chan_switch_ie_t; ++ ++#define DOT11_SWITCH_IE_LEN 3 /* length of IE data, not including 2 byte header */ ++/* CSA mode - 802.11h-2003 $7.3.2.20 */ ++#define DOT11_CSA_MODE_ADVISORY 0 /* no DOT11_CSA_MODE_NO_TX restriction imposed */ ++#define DOT11_CSA_MODE_NO_TX 1 /* no transmission upon receiving CSA frame. */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_action_switch_channel { ++ uint8 category; ++ uint8 action; ++ dot11_chan_switch_ie_t chan_switch_ie; /* for switch IE */ ++ dot11_brcm_extch_ie_t extch_ie; /* extension channel offset */ ++} BWL_POST_PACKED_STRUCT; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_csa_body { ++ uint8 mode; /* mode 0 or 1 */ ++ uint8 reg; /* regulatory class */ ++ uint8 channel; /* channel switch to */ ++ uint8 count; /* number of beacons before switching */ ++} BWL_POST_PACKED_STRUCT; ++ ++/* 11n Extended Channel Switch IE data structure */ ++BWL_PRE_PACKED_STRUCT struct dot11_ext_csa { ++ uint8 id; /* id DOT11_MNG_EXT_CHANNEL_SWITCH_ID */ ++ uint8 len; /* length of IE */ ++ struct dot11_csa_body b; /* body of the ie */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_ext_csa dot11_ext_csa_ie_t; ++#define DOT11_EXT_CSA_IE_LEN 4 /* length of extended channel switch IE body */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_action_ext_csa { ++ uint8 category; ++ uint8 action; ++ dot11_ext_csa_ie_t chan_switch_ie; /* for switch IE */ ++} BWL_POST_PACKED_STRUCT; ++ ++BWL_PRE_PACKED_STRUCT struct dot11y_action_ext_csa { ++ uint8 category; ++ uint8 action; ++ struct dot11_csa_body b; /* body of the ie */ ++} BWL_POST_PACKED_STRUCT; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_obss_coex { ++ uint8 id; ++ uint8 len; ++ uint8 info; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_obss_coex dot11_obss_coex_t; ++#define DOT11_OBSS_COEXINFO_LEN 1 /* length of OBSS Coexistence INFO IE */ ++ ++#define DOT11_OBSS_COEX_INFO_REQ 0x01 ++#define DOT11_OBSS_COEX_40MHZ_INTOLERANT 0x02 ++#define DOT11_OBSS_COEX_20MHZ_WIDTH_REQ 0x04 ++ ++BWL_PRE_PACKED_STRUCT struct dot11_obss_chanlist { ++ uint8 id; ++ uint8 len; ++ uint8 regclass; ++ uint8 chanlist[1]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_obss_chanlist dot11_obss_chanlist_t; ++#define DOT11_OBSS_CHANLIST_FIXED_LEN 1 /* fixed length of regclass */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_extcap_ie { ++ uint8 id; ++ uint8 len; ++ uint8 cap[1]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_extcap_ie dot11_extcap_ie_t; ++ ++#define DOT11_EXTCAP_LEN_MAX 7 ++#define DOT11_EXTCAP_LEN_COEX 1 ++#define DOT11_EXTCAP_LEN_BT 3 ++#define DOT11_EXTCAP_LEN_IW 4 ++#define DOT11_EXTCAP_LEN_SI 6 ++ ++#define DOT11_EXTCAP_LEN_TDLS 5 ++BWL_PRE_PACKED_STRUCT struct dot11_extcap { ++ uint8 extcap[DOT11_EXTCAP_LEN_TDLS]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_extcap dot11_extcap_t; ++ ++/* TDLS Capabilities */ ++#define TDLS_CAP_TDLS 37 /* TDLS support */ ++#define TDLS_CAP_PU_BUFFER_STA 28 /* TDLS Peer U-APSD buffer STA support */ ++#define TDLS_CAP_PEER_PSM 20 /* TDLS Peer PSM support */ ++#define TDLS_CAP_CH_SW 30 /* TDLS Channel switch */ ++#define TDLS_CAP_PROH 38 /* TDLS prohibited */ ++#define TDLS_CAP_CH_SW_PROH 39 /* TDLS Channel switch prohibited */ ++ ++#define TDLS_CAP_MAX_BIT 39 /* TDLS max bit defined in ext cap */ ++ ++/* 802.11h/802.11k Measurement Request/Report IEs */ ++/* Measurement Type field */ ++#define DOT11_MEASURE_TYPE_BASIC 0 /* d11 measurement basic type */ ++#define DOT11_MEASURE_TYPE_CCA 1 /* d11 measurement CCA type */ ++#define DOT11_MEASURE_TYPE_RPI 2 /* d11 measurement RPI type */ ++#define DOT11_MEASURE_TYPE_CHLOAD 3 /* d11 measurement Channel Load type */ ++#define DOT11_MEASURE_TYPE_NOISE 4 /* d11 measurement Noise Histogram type */ ++#define DOT11_MEASURE_TYPE_BEACON 5 /* d11 measurement Beacon type */ ++#define DOT11_MEASURE_TYPE_FRAME 6 /* d11 measurement Frame type */ ++#define DOT11_MEASURE_TYPE_STATS 7 /* d11 measurement STA Statistics type */ ++#define DOT11_MEASURE_TYPE_LCI 8 /* d11 measurement LCI type */ ++#define DOT11_MEASURE_TYPE_TXSTREAM 9 /* d11 measurement TX Stream type */ ++#define DOT11_MEASURE_TYPE_PAUSE 255 /* d11 measurement pause type */ ++ ++/* Measurement Request Modes */ ++#define DOT11_MEASURE_MODE_PARALLEL (1<<0) /* d11 measurement parallel */ ++#define DOT11_MEASURE_MODE_ENABLE (1<<1) /* d11 measurement enable */ ++#define DOT11_MEASURE_MODE_REQUEST (1<<2) /* d11 measurement request */ ++#define DOT11_MEASURE_MODE_REPORT (1<<3) /* d11 measurement report */ ++#define DOT11_MEASURE_MODE_DUR (1<<4) /* d11 measurement dur mandatory */ ++/* Measurement Report Modes */ ++#define DOT11_MEASURE_MODE_LATE (1<<0) /* d11 measurement late */ ++#define DOT11_MEASURE_MODE_INCAPABLE (1<<1) /* d11 measurement incapable */ ++#define DOT11_MEASURE_MODE_REFUSED (1<<2) /* d11 measurement refuse */ ++/* Basic Measurement Map bits */ ++#define DOT11_MEASURE_BASIC_MAP_BSS ((uint8)(1<<0)) /* d11 measurement basic map BSS */ ++#define DOT11_MEASURE_BASIC_MAP_OFDM ((uint8)(1<<1)) /* d11 measurement map OFDM */ ++#define DOT11_MEASURE_BASIC_MAP_UKNOWN ((uint8)(1<<2)) /* d11 measurement map unknown */ ++#define DOT11_MEASURE_BASIC_MAP_RADAR ((uint8)(1<<3)) /* d11 measurement map radar */ ++#define DOT11_MEASURE_BASIC_MAP_UNMEAS ((uint8)(1<<4)) /* d11 measurement map unmeasuremnt */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_meas_req { ++ uint8 id; ++ uint8 len; ++ uint8 token; ++ uint8 mode; ++ uint8 type; ++ uint8 channel; ++ uint8 start_time[8]; ++ uint16 duration; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_meas_req dot11_meas_req_t; ++#define DOT11_MNG_IE_MREQ_LEN 14 /* d11 measurement request IE length */ ++/* length of Measure Request IE data not including variable len */ ++#define DOT11_MNG_IE_MREQ_FIXED_LEN 3 /* d11 measurement request IE fixed length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_meas_rep { ++ uint8 id; ++ uint8 len; ++ uint8 token; ++ uint8 mode; ++ uint8 type; ++ BWL_PRE_PACKED_STRUCT union ++ { ++ BWL_PRE_PACKED_STRUCT struct { ++ uint8 channel; ++ uint8 start_time[8]; ++ uint16 duration; ++ uint8 map; ++ } BWL_POST_PACKED_STRUCT basic; ++ uint8 data[1]; ++ } BWL_POST_PACKED_STRUCT rep; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_meas_rep dot11_meas_rep_t; ++ ++/* length of Measure Report IE data not including variable len */ ++#define DOT11_MNG_IE_MREP_FIXED_LEN 3 /* d11 measurement response IE fixed length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_meas_rep_basic { ++ uint8 channel; ++ uint8 start_time[8]; ++ uint16 duration; ++ uint8 map; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_meas_rep_basic dot11_meas_rep_basic_t; ++#define DOT11_MEASURE_BASIC_REP_LEN 12 /* d11 measurement basic report length */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_quiet { ++ uint8 id; ++ uint8 len; ++ uint8 count; /* TBTTs until beacon interval in quiet starts */ ++ uint8 period; /* Beacon intervals between periodic quiet periods ? */ ++ uint16 duration; /* Length of quiet period, in TU's */ ++ uint16 offset; /* TU's offset from TBTT in Count field */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_quiet dot11_quiet_t; ++ ++BWL_PRE_PACKED_STRUCT struct chan_map_tuple { ++ uint8 channel; ++ uint8 map; ++} BWL_POST_PACKED_STRUCT; ++typedef struct chan_map_tuple chan_map_tuple_t; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_ibss_dfs { ++ uint8 id; ++ uint8 len; ++ uint8 eaddr[ETHER_ADDR_LEN]; ++ uint8 interval; ++ chan_map_tuple_t map[1]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_ibss_dfs dot11_ibss_dfs_t; ++ ++/* WME Elements */ ++#define WME_OUI "\x00\x50\xf2" /* WME OUI */ ++#define WME_OUI_LEN 3 ++#define WME_OUI_TYPE 2 /* WME type */ ++#define WME_TYPE 2 /* WME type, deprecated */ ++#define WME_SUBTYPE_IE 0 /* Information Element */ ++#define WME_SUBTYPE_PARAM_IE 1 /* Parameter Element */ ++#define WME_SUBTYPE_TSPEC 2 /* Traffic Specification */ ++#define WME_VER 1 /* WME version */ ++ ++/* WME Access Category Indices (ACIs) */ ++#define AC_BE 0 /* Best Effort */ ++#define AC_BK 1 /* Background */ ++#define AC_VI 2 /* Video */ ++#define AC_VO 3 /* Voice */ ++#define AC_COUNT 4 /* number of ACs */ ++ ++typedef uint8 ac_bitmap_t; /* AC bitmap of (1 << AC_xx) */ ++ ++#define AC_BITMAP_NONE 0x0 /* No ACs */ ++#define AC_BITMAP_ALL 0xf /* All ACs */ ++#define AC_BITMAP_TST(ab, ac) (((ab) & (1 << (ac))) != 0) ++#define AC_BITMAP_SET(ab, ac) (((ab) |= (1 << (ac)))) ++#define AC_BITMAP_RESET(ab, ac) (((ab) &= ~(1 << (ac)))) ++ ++/* WME Information Element (IE) */ ++BWL_PRE_PACKED_STRUCT struct wme_ie { ++ uint8 oui[3]; ++ uint8 type; ++ uint8 subtype; ++ uint8 version; ++ uint8 qosinfo; ++} BWL_POST_PACKED_STRUCT; ++typedef struct wme_ie wme_ie_t; ++#define WME_IE_LEN 7 /* WME IE length */ ++ ++BWL_PRE_PACKED_STRUCT struct edcf_acparam { ++ uint8 ACI; ++ uint8 ECW; ++ uint16 TXOP; /* stored in network order (ls octet first) */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct edcf_acparam edcf_acparam_t; ++ ++/* WME Parameter Element (PE) */ ++BWL_PRE_PACKED_STRUCT struct wme_param_ie { ++ uint8 oui[3]; ++ uint8 type; ++ uint8 subtype; ++ uint8 version; ++ uint8 qosinfo; ++ uint8 rsvd; ++ edcf_acparam_t acparam[AC_COUNT]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct wme_param_ie wme_param_ie_t; ++#define WME_PARAM_IE_LEN 24 /* WME Parameter IE length */ ++ ++/* QoS Info field for IE as sent from AP */ ++#define WME_QI_AP_APSD_MASK 0x80 /* U-APSD Supported mask */ ++#define WME_QI_AP_APSD_SHIFT 7 /* U-APSD Supported shift */ ++#define WME_QI_AP_COUNT_MASK 0x0f /* Parameter set count mask */ ++#define WME_QI_AP_COUNT_SHIFT 0 /* Parameter set count shift */ ++ ++/* QoS Info field for IE as sent from STA */ ++#define WME_QI_STA_MAXSPLEN_MASK 0x60 /* Max Service Period Length mask */ ++#define WME_QI_STA_MAXSPLEN_SHIFT 5 /* Max Service Period Length shift */ ++#define WME_QI_STA_APSD_ALL_MASK 0xf /* APSD all AC bits mask */ ++#define WME_QI_STA_APSD_ALL_SHIFT 0 /* APSD all AC bits shift */ ++#define WME_QI_STA_APSD_BE_MASK 0x8 /* APSD AC_BE mask */ ++#define WME_QI_STA_APSD_BE_SHIFT 3 /* APSD AC_BE shift */ ++#define WME_QI_STA_APSD_BK_MASK 0x4 /* APSD AC_BK mask */ ++#define WME_QI_STA_APSD_BK_SHIFT 2 /* APSD AC_BK shift */ ++#define WME_QI_STA_APSD_VI_MASK 0x2 /* APSD AC_VI mask */ ++#define WME_QI_STA_APSD_VI_SHIFT 1 /* APSD AC_VI shift */ ++#define WME_QI_STA_APSD_VO_MASK 0x1 /* APSD AC_VO mask */ ++#define WME_QI_STA_APSD_VO_SHIFT 0 /* APSD AC_VO shift */ ++ ++/* ACI */ ++#define EDCF_AIFSN_MIN 1 /* AIFSN minimum value */ ++#define EDCF_AIFSN_MAX 15 /* AIFSN maximum value */ ++#define EDCF_AIFSN_MASK 0x0f /* AIFSN mask */ ++#define EDCF_ACM_MASK 0x10 /* ACM mask */ ++#define EDCF_ACI_MASK 0x60 /* ACI mask */ ++#define EDCF_ACI_SHIFT 5 /* ACI shift */ ++#define EDCF_AIFSN_SHIFT 12 /* 4 MSB(0xFFF) in ifs_ctl for AC idx */ ++ ++/* ECW */ ++#define EDCF_ECW_MIN 0 /* cwmin/cwmax exponent minimum value */ ++#define EDCF_ECW_MAX 15 /* cwmin/cwmax exponent maximum value */ ++#define EDCF_ECW2CW(exp) ((1 << (exp)) - 1) ++#define EDCF_ECWMIN_MASK 0x0f /* cwmin exponent form mask */ ++#define EDCF_ECWMAX_MASK 0xf0 /* cwmax exponent form mask */ ++#define EDCF_ECWMAX_SHIFT 4 /* cwmax exponent form shift */ ++ ++/* TXOP */ ++#define EDCF_TXOP_MIN 0 /* TXOP minimum value */ ++#define EDCF_TXOP_MAX 65535 /* TXOP maximum value */ ++#define EDCF_TXOP2USEC(txop) ((txop) << 5) ++ ++/* Default BE ACI value for non-WME connection STA */ ++#define NON_EDCF_AC_BE_ACI_STA 0x02 ++ ++/* Default EDCF parameters that AP advertises for STA to use; WMM draft Table 12 */ ++#define EDCF_AC_BE_ACI_STA 0x03 /* STA ACI value for best effort AC */ ++#define EDCF_AC_BE_ECW_STA 0xA4 /* STA ECW value for best effort AC */ ++#define EDCF_AC_BE_TXOP_STA 0x0000 /* STA TXOP value for best effort AC */ ++#define EDCF_AC_BK_ACI_STA 0x27 /* STA ACI value for background AC */ ++#define EDCF_AC_BK_ECW_STA 0xA4 /* STA ECW value for background AC */ ++#define EDCF_AC_BK_TXOP_STA 0x0000 /* STA TXOP value for background AC */ ++#define EDCF_AC_VI_ACI_STA 0x42 /* STA ACI value for video AC */ ++#define EDCF_AC_VI_ECW_STA 0x43 /* STA ECW value for video AC */ ++#define EDCF_AC_VI_TXOP_STA 0x005e /* STA TXOP value for video AC */ ++#define EDCF_AC_VO_ACI_STA 0x62 /* STA ACI value for audio AC */ ++#define EDCF_AC_VO_ECW_STA 0x32 /* STA ECW value for audio AC */ ++#define EDCF_AC_VO_TXOP_STA 0x002f /* STA TXOP value for audio AC */ ++ ++/* Default EDCF parameters that AP uses; WMM draft Table 14 */ ++#define EDCF_AC_BE_ACI_AP 0x03 /* AP ACI value for best effort AC */ ++#define EDCF_AC_BE_ECW_AP 0x64 /* AP ECW value for best effort AC */ ++#define EDCF_AC_BE_TXOP_AP 0x0000 /* AP TXOP value for best effort AC */ ++#define EDCF_AC_BK_ACI_AP 0x27 /* AP ACI value for background AC */ ++#define EDCF_AC_BK_ECW_AP 0xA4 /* AP ECW value for background AC */ ++#define EDCF_AC_BK_TXOP_AP 0x0000 /* AP TXOP value for background AC */ ++#define EDCF_AC_VI_ACI_AP 0x41 /* AP ACI value for video AC */ ++#define EDCF_AC_VI_ECW_AP 0x43 /* AP ECW value for video AC */ ++#define EDCF_AC_VI_TXOP_AP 0x005e /* AP TXOP value for video AC */ ++#define EDCF_AC_VO_ACI_AP 0x61 /* AP ACI value for audio AC */ ++#define EDCF_AC_VO_ECW_AP 0x32 /* AP ECW value for audio AC */ ++#define EDCF_AC_VO_TXOP_AP 0x002f /* AP TXOP value for audio AC */ ++ ++/* EDCA Parameter IE */ ++BWL_PRE_PACKED_STRUCT struct edca_param_ie { ++ uint8 qosinfo; ++ uint8 rsvd; ++ edcf_acparam_t acparam[AC_COUNT]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct edca_param_ie edca_param_ie_t; ++#define EDCA_PARAM_IE_LEN 18 /* EDCA Parameter IE length */ ++ ++/* QoS Capability IE */ ++BWL_PRE_PACKED_STRUCT struct qos_cap_ie { ++ uint8 qosinfo; ++} BWL_POST_PACKED_STRUCT; ++typedef struct qos_cap_ie qos_cap_ie_t; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_qbss_load_ie { ++ uint8 id; /* 11, DOT11_MNG_QBSS_LOAD_ID */ ++ uint8 length; ++ uint16 station_count; /* total number of STAs associated */ ++ uint8 channel_utilization; /* % of time, normalized to 255, QAP sensed medium busy */ ++ uint16 aac; /* available admission capacity */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_qbss_load_ie dot11_qbss_load_ie_t; ++#define BSS_LOAD_IE_SIZE 7 /* BSS load IE size */ ++ ++/* nom_msdu_size */ ++#define FIXED_MSDU_SIZE 0x8000 /* MSDU size is fixed */ ++#define MSDU_SIZE_MASK 0x7fff /* (Nominal or fixed) MSDU size */ ++ ++/* surplus_bandwidth */ ++/* Represented as 3 bits of integer, binary point, 13 bits fraction */ ++#define INTEGER_SHIFT 13 /* integer shift */ ++#define FRACTION_MASK 0x1FFF /* fraction mask */ ++ ++/* Management Notification Frame */ ++BWL_PRE_PACKED_STRUCT struct dot11_management_notification { ++ uint8 category; /* DOT11_ACTION_NOTIFICATION */ ++ uint8 action; ++ uint8 token; ++ uint8 status; ++ uint8 data[1]; /* Elements */ ++} BWL_POST_PACKED_STRUCT; ++#define DOT11_MGMT_NOTIFICATION_LEN 4 /* Fixed length */ ++ ++/* Timeout Interval IE */ ++BWL_PRE_PACKED_STRUCT struct ti_ie { ++ uint8 ti_type; ++ uint32 ti_val; ++} BWL_POST_PACKED_STRUCT; ++typedef struct ti_ie ti_ie_t; ++#define TI_TYPE_REASSOC_DEADLINE 1 ++#define TI_TYPE_KEY_LIFETIME 2 ++ ++/* WME Action Codes */ ++#define WME_ADDTS_REQUEST 0 /* WME ADDTS request */ ++#define WME_ADDTS_RESPONSE 1 /* WME ADDTS response */ ++#define WME_DELTS_REQUEST 2 /* WME DELTS request */ ++ ++/* WME Setup Response Status Codes */ ++#define WME_ADMISSION_ACCEPTED 0 /* WME admission accepted */ ++#define WME_INVALID_PARAMETERS 1 /* WME invalide parameters */ ++#define WME_ADMISSION_REFUSED 3 /* WME admission refused */ ++ ++/* Macro to take a pointer to a beacon or probe response ++ * body and return the char* pointer to the SSID info element ++ */ ++#define BCN_PRB_SSID(body) ((char*)(body) + DOT11_BCN_PRB_LEN) ++ ++/* Authentication frame payload constants */ ++#define DOT11_OPEN_SYSTEM 0 /* d11 open authentication */ ++#define DOT11_SHARED_KEY 1 /* d11 shared authentication */ ++#define DOT11_FAST_BSS 2 /* d11 fast bss authentication */ ++#define DOT11_CHALLENGE_LEN 128 /* d11 challenge text length */ ++ ++/* Frame control macros */ ++#define FC_PVER_MASK 0x3 /* PVER mask */ ++#define FC_PVER_SHIFT 0 /* PVER shift */ ++#define FC_TYPE_MASK 0xC /* type mask */ ++#define FC_TYPE_SHIFT 2 /* type shift */ ++#define FC_SUBTYPE_MASK 0xF0 /* subtype mask */ ++#define FC_SUBTYPE_SHIFT 4 /* subtype shift */ ++#define FC_TODS 0x100 /* to DS */ ++#define FC_TODS_SHIFT 8 /* to DS shift */ ++#define FC_FROMDS 0x200 /* from DS */ ++#define FC_FROMDS_SHIFT 9 /* from DS shift */ ++#define FC_MOREFRAG 0x400 /* more frag. */ ++#define FC_MOREFRAG_SHIFT 10 /* more frag. shift */ ++#define FC_RETRY 0x800 /* retry */ ++#define FC_RETRY_SHIFT 11 /* retry shift */ ++#define FC_PM 0x1000 /* PM */ ++#define FC_PM_SHIFT 12 /* PM shift */ ++#define FC_MOREDATA 0x2000 /* more data */ ++#define FC_MOREDATA_SHIFT 13 /* more data shift */ ++#define FC_WEP 0x4000 /* WEP */ ++#define FC_WEP_SHIFT 14 /* WEP shift */ ++#define FC_ORDER 0x8000 /* order */ ++#define FC_ORDER_SHIFT 15 /* order shift */ ++ ++/* sequence control macros */ ++#define SEQNUM_SHIFT 4 /* seq. number shift */ ++#define SEQNUM_MAX 0x1000 /* max seqnum + 1 */ ++#define FRAGNUM_MASK 0xF /* frag. number mask */ ++ ++/* Frame Control type/subtype defs */ ++ ++/* FC Types */ ++#define FC_TYPE_MNG 0 /* management type */ ++#define FC_TYPE_CTL 1 /* control type */ ++#define FC_TYPE_DATA 2 /* data type */ ++ ++/* Management Subtypes */ ++#define FC_SUBTYPE_ASSOC_REQ 0 /* assoc. request */ ++#define FC_SUBTYPE_ASSOC_RESP 1 /* assoc. response */ ++#define FC_SUBTYPE_REASSOC_REQ 2 /* reassoc. request */ ++#define FC_SUBTYPE_REASSOC_RESP 3 /* reassoc. response */ ++#define FC_SUBTYPE_PROBE_REQ 4 /* probe request */ ++#define FC_SUBTYPE_PROBE_RESP 5 /* probe response */ ++#define FC_SUBTYPE_BEACON 8 /* beacon */ ++#define FC_SUBTYPE_ATIM 9 /* ATIM */ ++#define FC_SUBTYPE_DISASSOC 10 /* disassoc. */ ++#define FC_SUBTYPE_AUTH 11 /* authentication */ ++#define FC_SUBTYPE_DEAUTH 12 /* de-authentication */ ++#define FC_SUBTYPE_ACTION 13 /* action */ ++#define FC_SUBTYPE_ACTION_NOACK 14 /* action no-ack */ ++ ++/* Control Subtypes */ ++#define FC_SUBTYPE_CTL_WRAPPER 7 /* Control Wrapper */ ++#define FC_SUBTYPE_BLOCKACK_REQ 8 /* Block Ack Req */ ++#define FC_SUBTYPE_BLOCKACK 9 /* Block Ack */ ++#define FC_SUBTYPE_PS_POLL 10 /* PS poll */ ++#define FC_SUBTYPE_RTS 11 /* RTS */ ++#define FC_SUBTYPE_CTS 12 /* CTS */ ++#define FC_SUBTYPE_ACK 13 /* ACK */ ++#define FC_SUBTYPE_CF_END 14 /* CF-END */ ++#define FC_SUBTYPE_CF_END_ACK 15 /* CF-END ACK */ ++ ++/* Data Subtypes */ ++#define FC_SUBTYPE_DATA 0 /* Data */ ++#define FC_SUBTYPE_DATA_CF_ACK 1 /* Data + CF-ACK */ ++#define FC_SUBTYPE_DATA_CF_POLL 2 /* Data + CF-Poll */ ++#define FC_SUBTYPE_DATA_CF_ACK_POLL 3 /* Data + CF-Ack + CF-Poll */ ++#define FC_SUBTYPE_NULL 4 /* Null */ ++#define FC_SUBTYPE_CF_ACK 5 /* CF-Ack */ ++#define FC_SUBTYPE_CF_POLL 6 /* CF-Poll */ ++#define FC_SUBTYPE_CF_ACK_POLL 7 /* CF-Ack + CF-Poll */ ++#define FC_SUBTYPE_QOS_DATA 8 /* QoS Data */ ++#define FC_SUBTYPE_QOS_DATA_CF_ACK 9 /* QoS Data + CF-Ack */ ++#define FC_SUBTYPE_QOS_DATA_CF_POLL 10 /* QoS Data + CF-Poll */ ++#define FC_SUBTYPE_QOS_DATA_CF_ACK_POLL 11 /* QoS Data + CF-Ack + CF-Poll */ ++#define FC_SUBTYPE_QOS_NULL 12 /* QoS Null */ ++#define FC_SUBTYPE_QOS_CF_POLL 14 /* QoS CF-Poll */ ++#define FC_SUBTYPE_QOS_CF_ACK_POLL 15 /* QoS CF-Ack + CF-Poll */ ++ ++/* Data Subtype Groups */ ++#define FC_SUBTYPE_ANY_QOS(s) (((s) & 8) != 0) ++#define FC_SUBTYPE_ANY_NULL(s) (((s) & 4) != 0) ++#define FC_SUBTYPE_ANY_CF_POLL(s) (((s) & 2) != 0) ++#define FC_SUBTYPE_ANY_CF_ACK(s) (((s) & 1) != 0) ++ ++/* Type/Subtype Combos */ ++#define FC_KIND_MASK (FC_TYPE_MASK | FC_SUBTYPE_MASK) /* FC kind mask */ ++ ++#define FC_KIND(t, s) (((t) << FC_TYPE_SHIFT) | ((s) << FC_SUBTYPE_SHIFT)) /* FC kind */ ++ ++#define FC_SUBTYPE(fc) (((fc) & FC_SUBTYPE_MASK) >> FC_SUBTYPE_SHIFT) /* Subtype from FC */ ++#define FC_TYPE(fc) (((fc) & FC_TYPE_MASK) >> FC_TYPE_SHIFT) /* Type from FC */ ++ ++#define FC_ASSOC_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ASSOC_REQ) /* assoc. request */ ++#define FC_ASSOC_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ASSOC_RESP) /* assoc. response */ ++#define FC_REASSOC_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_REQ) /* reassoc. request */ ++#define FC_REASSOC_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_RESP) /* reassoc. response */ ++#define FC_PROBE_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_REQ) /* probe request */ ++#define FC_PROBE_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_RESP) /* probe response */ ++#define FC_BEACON FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_BEACON) /* beacon */ ++#define FC_DISASSOC FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DISASSOC) /* disassoc */ ++#define FC_AUTH FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_AUTH) /* authentication */ ++#define FC_DEAUTH FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DEAUTH) /* deauthentication */ ++#define FC_ACTION FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ACTION) /* action */ ++#define FC_ACTION_NOACK FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ACTION_NOACK) /* action no-ack */ ++ ++#define FC_CTL_WRAPPER FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CTL_WRAPPER) /* Control Wrapper */ ++#define FC_BLOCKACK_REQ FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_BLOCKACK_REQ) /* Block Ack Req */ ++#define FC_BLOCKACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_BLOCKACK) /* Block Ack */ ++#define FC_PS_POLL FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_PS_POLL) /* PS poll */ ++#define FC_RTS FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_RTS) /* RTS */ ++#define FC_CTS FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CTS) /* CTS */ ++#define FC_ACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_ACK) /* ACK */ ++#define FC_CF_END FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CF_END) /* CF-END */ ++#define FC_CF_END_ACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CF_END_ACK) /* CF-END ACK */ ++ ++#define FC_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_DATA) /* data */ ++#define FC_NULL_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_NULL) /* null data */ ++#define FC_DATA_CF_ACK FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_DATA_CF_ACK) /* data CF ACK */ ++#define FC_QOS_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_QOS_DATA) /* QoS data */ ++#define FC_QOS_NULL FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_QOS_NULL) /* QoS null */ ++ ++/* QoS Control Field */ ++ ++/* 802.1D Priority */ ++#define QOS_PRIO_SHIFT 0 /* QoS priority shift */ ++#define QOS_PRIO_MASK 0x0007 /* QoS priority mask */ ++#define QOS_PRIO(qos) (((qos) & QOS_PRIO_MASK) >> QOS_PRIO_SHIFT) /* QoS priority */ ++ ++/* Traffic Identifier */ ++#define QOS_TID_SHIFT 0 /* QoS TID shift */ ++#define QOS_TID_MASK 0x000f /* QoS TID mask */ ++#define QOS_TID(qos) (((qos) & QOS_TID_MASK) >> QOS_TID_SHIFT) /* QoS TID */ ++ ++/* End of Service Period (U-APSD) */ ++#define QOS_EOSP_SHIFT 4 /* QoS End of Service Period shift */ ++#define QOS_EOSP_MASK 0x0010 /* QoS End of Service Period mask */ ++#define QOS_EOSP(qos) (((qos) & QOS_EOSP_MASK) >> QOS_EOSP_SHIFT) /* Qos EOSP */ ++ ++/* Ack Policy */ ++#define QOS_ACK_NORMAL_ACK 0 /* Normal Ack */ ++#define QOS_ACK_NO_ACK 1 /* No Ack (eg mcast) */ ++#define QOS_ACK_NO_EXP_ACK 2 /* No Explicit Ack */ ++#define QOS_ACK_BLOCK_ACK 3 /* Block Ack */ ++#define QOS_ACK_SHIFT 5 /* QoS ACK shift */ ++#define QOS_ACK_MASK 0x0060 /* QoS ACK mask */ ++#define QOS_ACK(qos) (((qos) & QOS_ACK_MASK) >> QOS_ACK_SHIFT) /* QoS ACK */ ++ ++/* A-MSDU flag */ ++#define QOS_AMSDU_SHIFT 7 /* AMSDU shift */ ++#define QOS_AMSDU_MASK 0x0080 /* AMSDU mask */ ++ ++/* Management Frames */ ++ ++/* Management Frame Constants */ ++ ++/* Fixed fields */ ++#define DOT11_MNG_AUTH_ALGO_LEN 2 /* d11 management auth. algo. length */ ++#define DOT11_MNG_AUTH_SEQ_LEN 2 /* d11 management auth. seq. length */ ++#define DOT11_MNG_BEACON_INT_LEN 2 /* d11 management beacon interval length */ ++#define DOT11_MNG_CAP_LEN 2 /* d11 management cap. length */ ++#define DOT11_MNG_AP_ADDR_LEN 6 /* d11 management AP address length */ ++#define DOT11_MNG_LISTEN_INT_LEN 2 /* d11 management listen interval length */ ++#define DOT11_MNG_REASON_LEN 2 /* d11 management reason length */ ++#define DOT11_MNG_AID_LEN 2 /* d11 management AID length */ ++#define DOT11_MNG_STATUS_LEN 2 /* d11 management status length */ ++#define DOT11_MNG_TIMESTAMP_LEN 8 /* d11 management timestamp length */ ++ ++/* DUR/ID field in assoc resp is 0xc000 | AID */ ++#define DOT11_AID_MASK 0x3fff /* d11 AID mask */ ++ ++/* Reason Codes */ ++#define DOT11_RC_RESERVED 0 /* d11 RC reserved */ ++#define DOT11_RC_UNSPECIFIED 1 /* Unspecified reason */ ++#define DOT11_RC_AUTH_INVAL 2 /* Previous authentication no longer valid */ ++#define DOT11_RC_DEAUTH_LEAVING 3 /* Deauthenticated because sending station ++ * is leaving (or has left) IBSS or ESS ++ */ ++#define DOT11_RC_INACTIVITY 4 /* Disassociated due to inactivity */ ++#define DOT11_RC_BUSY 5 /* Disassociated because AP is unable to handle ++ * all currently associated stations ++ */ ++#define DOT11_RC_INVAL_CLASS_2 6 /* Class 2 frame received from ++ * nonauthenticated station ++ */ ++#define DOT11_RC_INVAL_CLASS_3 7 /* Class 3 frame received from ++ * nonassociated station ++ */ ++#define DOT11_RC_DISASSOC_LEAVING 8 /* Disassociated because sending station is ++ * leaving (or has left) BSS ++ */ ++#define DOT11_RC_NOT_AUTH 9 /* Station requesting (re)association is not ++ * authenticated with responding station ++ */ ++#define DOT11_RC_BAD_PC 10 /* Unacceptable power capability element */ ++#define DOT11_RC_BAD_CHANNELS 11 /* Unacceptable supported channels element */ ++/* 12 is unused */ ++ ++/* 32-39 are QSTA specific reasons added in 11e */ ++#define DOT11_RC_UNSPECIFIED_QOS 32 /* unspecified QoS-related reason */ ++#define DOT11_RC_INSUFFCIENT_BW 33 /* QAP lacks sufficient bandwidth */ ++#define DOT11_RC_EXCESSIVE_FRAMES 34 /* excessive number of frames need ack */ ++#define DOT11_RC_TX_OUTSIDE_TXOP 35 /* transmitting outside the limits of txop */ ++#define DOT11_RC_LEAVING_QBSS 36 /* QSTA is leaving the QBSS (or restting) */ ++#define DOT11_RC_BAD_MECHANISM 37 /* does not want to use the mechanism */ ++#define DOT11_RC_SETUP_NEEDED 38 /* mechanism needs a setup */ ++#define DOT11_RC_TIMEOUT 39 /* timeout */ ++ ++#define DOT11_RC_MAX 23 /* Reason codes > 23 are reserved */ ++ ++#define DOT11_RC_TDLS_PEER_UNREACH 25 ++#define DOT11_RC_TDLS_DOWN_UNSPECIFIED 26 ++ ++/* Status Codes */ ++#define DOT11_SC_SUCCESS 0 /* Successful */ ++#define DOT11_SC_FAILURE 1 /* Unspecified failure */ ++#define DOT11_SC_TDLS_WAKEUP_SCH_ALT 2 /* TDLS wakeup schedule rejected but alternative */ ++ /* schedule provided */ ++#define DOT11_SC_TDLS_WAKEUP_SCH_REJ 3 /* TDLS wakeup schedule rejected */ ++#define DOT11_SC_TDLS_SEC_DISABLED 5 /* TDLS Security disabled */ ++#define DOT11_SC_LIFETIME_REJ 6 /* Unacceptable lifetime */ ++#define DOT11_SC_NOT_SAME_BSS 7 /* Not in same BSS */ ++#define DOT11_SC_CAP_MISMATCH 10 /* Cannot support all requested ++ * capabilities in the Capability ++ * Information field ++ */ ++#define DOT11_SC_REASSOC_FAIL 11 /* Reassociation denied due to inability ++ * to confirm that association exists ++ */ ++#define DOT11_SC_ASSOC_FAIL 12 /* Association denied due to reason ++ * outside the scope of this standard ++ */ ++#define DOT11_SC_AUTH_MISMATCH 13 /* Responding station does not support ++ * the specified authentication ++ * algorithm ++ */ ++#define DOT11_SC_AUTH_SEQ 14 /* Received an Authentication frame ++ * with authentication transaction ++ * sequence number out of expected ++ * sequence ++ */ ++#define DOT11_SC_AUTH_CHALLENGE_FAIL 15 /* Authentication rejected because of ++ * challenge failure ++ */ ++#define DOT11_SC_AUTH_TIMEOUT 16 /* Authentication rejected due to timeout ++ * waiting for next frame in sequence ++ */ ++#define DOT11_SC_ASSOC_BUSY_FAIL 17 /* Association denied because AP is ++ * unable to handle additional ++ * associated stations ++ */ ++#define DOT11_SC_ASSOC_RATE_MISMATCH 18 /* Association denied due to requesting ++ * station not supporting all of the ++ * data rates in the BSSBasicRateSet ++ * parameter ++ */ ++#define DOT11_SC_ASSOC_SHORT_REQUIRED 19 /* Association denied due to requesting ++ * station not supporting the Short ++ * Preamble option ++ */ ++#define DOT11_SC_ASSOC_PBCC_REQUIRED 20 /* Association denied due to requesting ++ * station not supporting the PBCC ++ * Modulation option ++ */ ++#define DOT11_SC_ASSOC_AGILITY_REQUIRED 21 /* Association denied due to requesting ++ * station not supporting the Channel ++ * Agility option ++ */ ++#define DOT11_SC_ASSOC_SPECTRUM_REQUIRED 22 /* Association denied because Spectrum ++ * Management capability is required. ++ */ ++#define DOT11_SC_ASSOC_BAD_POWER_CAP 23 /* Association denied because the info ++ * in the Power Cap element is ++ * unacceptable. ++ */ ++#define DOT11_SC_ASSOC_BAD_SUP_CHANNELS 24 /* Association denied because the info ++ * in the Supported Channel element is ++ * unacceptable ++ */ ++#define DOT11_SC_ASSOC_SHORTSLOT_REQUIRED 25 /* Association denied due to requesting ++ * station not supporting the Short Slot ++ * Time option ++ */ ++#define DOT11_SC_ASSOC_ERPBCC_REQUIRED 26 /* Association denied due to requesting ++ * station not supporting the ER-PBCC ++ * Modulation option ++ */ ++#define DOT11_SC_ASSOC_DSSOFDM_REQUIRED 27 /* Association denied due to requesting ++ * station not supporting the DSS-OFDM ++ * option ++ */ ++#define DOT11_SC_ASSOC_R0KH_UNREACHABLE 28 /* Association denied due to AP ++ * being unable to reach the R0 Key Holder ++ */ ++#define DOT11_SC_ASSOC_TRY_LATER 30 /* Association denied temporarily, try again later ++ */ ++#define DOT11_SC_ASSOC_MFP_VIOLATION 31 /* Association denied due to Robust Management ++ * frame policy violation ++ */ ++ ++#define DOT11_SC_DECLINED 37 /* request declined */ ++#define DOT11_SC_INVALID_PARAMS 38 /* One or more params have invalid values */ ++#define DOT11_SC_INVALID_PAIRWISE_CIPHER 42 /* invalid pairwise cipher */ ++#define DOT11_SC_INVALID_AKMP 43 /* Association denied due to invalid AKMP */ ++#define DOT11_SC_INVALID_RSNIE_CAP 45 /* invalid RSN IE capabilities */ ++#define DOT11_SC_DLS_NOT_ALLOWED 48 /* DLS is not allowed in the BSS by policy */ ++#define DOT11_SC_INVALID_PMKID 53 /* Association denied due to invalid PMKID */ ++#define DOT11_SC_INVALID_MDID 54 /* Association denied due to invalid MDID */ ++#define DOT11_SC_INVALID_FTIE 55 /* Association denied due to invalid FTIE */ ++ ++#define DOT11_SC_UNEXP_MSG 70 /* Unexpected message */ ++#define DOT11_SC_INVALID_SNONCE 71 /* Invalid SNonce */ ++#define DOT11_SC_INVALID_RSNIE 72 /* Invalid contents of RSNIE */ ++ ++/* Info Elts, length of INFORMATION portion of Info Elts */ ++#define DOT11_MNG_DS_PARAM_LEN 1 /* d11 management DS parameter length */ ++#define DOT11_MNG_IBSS_PARAM_LEN 2 /* d11 management IBSS parameter length */ ++ ++/* TIM Info element has 3 bytes fixed info in INFORMATION field, ++ * followed by 1 to 251 bytes of Partial Virtual Bitmap ++ */ ++#define DOT11_MNG_TIM_FIXED_LEN 3 /* d11 management TIM fixed length */ ++#define DOT11_MNG_TIM_DTIM_COUNT 0 /* d11 management DTIM count */ ++#define DOT11_MNG_TIM_DTIM_PERIOD 1 /* d11 management DTIM period */ ++#define DOT11_MNG_TIM_BITMAP_CTL 2 /* d11 management TIM BITMAP control */ ++#define DOT11_MNG_TIM_PVB 3 /* d11 management TIM PVB */ ++ ++/* TLV defines */ ++#define TLV_TAG_OFF 0 /* tag offset */ ++#define TLV_LEN_OFF 1 /* length offset */ ++#define TLV_HDR_LEN 2 /* header length */ ++#define TLV_BODY_OFF 2 /* body offset */ ++ ++/* Management Frame Information Element IDs */ ++#define DOT11_MNG_SSID_ID 0 /* d11 management SSID id */ ++#define DOT11_MNG_RATES_ID 1 /* d11 management rates id */ ++#define DOT11_MNG_FH_PARMS_ID 2 /* d11 management FH parameter id */ ++#define DOT11_MNG_DS_PARMS_ID 3 /* d11 management DS parameter id */ ++#define DOT11_MNG_CF_PARMS_ID 4 /* d11 management CF parameter id */ ++#define DOT11_MNG_TIM_ID 5 /* d11 management TIM id */ ++#define DOT11_MNG_IBSS_PARMS_ID 6 /* d11 management IBSS parameter id */ ++#define DOT11_MNG_COUNTRY_ID 7 /* d11 management country id */ ++#define DOT11_MNG_HOPPING_PARMS_ID 8 /* d11 management hopping parameter id */ ++#define DOT11_MNG_HOPPING_TABLE_ID 9 /* d11 management hopping table id */ ++#define DOT11_MNG_REQUEST_ID 10 /* d11 management request id */ ++#define DOT11_MNG_QBSS_LOAD_ID 11 /* d11 management QBSS Load id */ ++#define DOT11_MNG_EDCA_PARAM_ID 12 /* 11E EDCA Parameter id */ ++#define DOT11_MNG_CHALLENGE_ID 16 /* d11 management chanllenge id */ ++#define DOT11_MNG_PWR_CONSTRAINT_ID 32 /* 11H PowerConstraint */ ++#define DOT11_MNG_PWR_CAP_ID 33 /* 11H PowerCapability */ ++#define DOT11_MNG_TPC_REQUEST_ID 34 /* 11H TPC Request */ ++#define DOT11_MNG_TPC_REPORT_ID 35 /* 11H TPC Report */ ++#define DOT11_MNG_SUPP_CHANNELS_ID 36 /* 11H Supported Channels */ ++#define DOT11_MNG_CHANNEL_SWITCH_ID 37 /* 11H ChannelSwitch Announcement */ ++#define DOT11_MNG_MEASURE_REQUEST_ID 38 /* 11H MeasurementRequest */ ++#define DOT11_MNG_MEASURE_REPORT_ID 39 /* 11H MeasurementReport */ ++#define DOT11_MNG_QUIET_ID 40 /* 11H Quiet */ ++#define DOT11_MNG_IBSS_DFS_ID 41 /* 11H IBSS_DFS */ ++#define DOT11_MNG_ERP_ID 42 /* d11 management ERP id */ ++#define DOT11_MNG_TS_DELAY_ID 43 /* d11 management TS Delay id */ ++#define DOT11_MNG_HT_CAP 45 /* d11 mgmt HT cap id */ ++#define DOT11_MNG_QOS_CAP_ID 46 /* 11E QoS Capability id */ ++#define DOT11_MNG_NONERP_ID 47 /* d11 management NON-ERP id */ ++#define DOT11_MNG_RSN_ID 48 /* d11 management RSN id */ ++#define DOT11_MNG_EXT_RATES_ID 50 /* d11 management ext. rates id */ ++#define DOT11_MNG_AP_CHREP_ID 51 /* 11k AP Channel report id */ ++#define DOT11_MNG_NBR_REP_ID 52 /* 11k Neighbor report id */ ++#define DOT11_MNG_MDIE_ID 54 /* 11r Mobility domain id */ ++#define DOT11_MNG_FTIE_ID 55 /* 11r Fast Bss Transition id */ ++#define DOT11_MNG_FT_TI_ID 56 /* 11r Timeout Interval id */ ++#define DOT11_MNG_REGCLASS_ID 59 /* d11 management regulatory class id */ ++#define DOT11_MNG_EXT_CSA_ID 60 /* d11 Extended CSA */ ++#define DOT11_MNG_HT_ADD 61 /* d11 mgmt additional HT info */ ++#define DOT11_MNG_EXT_CHANNEL_OFFSET 62 /* d11 mgmt ext channel offset */ ++#ifdef BCMWAPI_WAI ++#define DOT11_MNG_WAPI_ID 68 /* d11 management WAPI id */ ++#endif ++#define DOT11_MNG_WAPI_ID 68 /* d11 management WAPI id */ ++#define DOT11_MNG_TIME_ADVERTISE_ID 69 /* 11p time advertisement */ ++#define DOT11_MNG_RRM_CAP_ID 70 /* 11k radio measurement capability */ ++#define DOT11_MNG_HT_BSS_COEXINFO_ID 72 /* d11 mgmt OBSS Coexistence INFO */ ++#define DOT11_MNG_HT_BSS_CHANNEL_REPORT_ID 73 /* d11 mgmt OBSS Intolerant Channel list */ ++#define DOT11_MNG_HT_OBSS_ID 74 /* d11 mgmt OBSS HT info */ ++#define DOT11_MNG_CHANNEL_USAGE 97 /* 11v channel usage */ ++#define DOT11_MNG_TIME_ZONE_ID 98 /* 11v time zone */ ++#define DOT11_MNG_LINK_IDENTIFIER_ID 101 /* 11z TDLS Link Identifier IE */ ++#define DOT11_MNG_WAKEUP_SCHEDULE_ID 102 /* 11z TDLS Wakeup Schedule IE */ ++#define DOT11_MNG_CHANNEL_SWITCH_TIMING_ID 104 /* 11z TDLS Channel Switch Timing IE */ ++#define DOT11_MNG_PTI_CONTROL_ID 105 /* 11z TDLS PTI Control IE */ ++#define DOT11_MNG_PU_BUFFER_STATUS_ID 106 /* 11z TDLS PU Buffer Status IE */ ++#define DOT11_MNG_INTERWORKING_ID 107 /* 11u interworking */ ++#define DOT11_MNG_ADVERTISEMENT_ID 108 /* 11u advertisement protocol */ ++#define DOT11_MNG_EXP_BW_REQ_ID 109 /* 11u expedited bandwith request */ ++#define DOT11_MNG_QOS_MAP_ID 110 /* 11u QoS map set */ ++#define DOT11_MNG_ROAM_CONSORT_ID 111 /* 11u roaming consortium */ ++#define DOT11_MNG_EMERGCY_ALERT_ID 112 /* 11u emergency alert identifier */ ++#define DOT11_MNG_EXT_CAP_ID 127 /* d11 mgmt ext capability */ ++#define DOT11_MNG_VHT_CAP_ID 191 /* d11 mgmt VHT cap id */ ++#define DOT11_MNG_VHT_OPERATION_ID 192 /* d11 mgmt VHT op id */ ++ ++#define DOT11_MNG_WPA_ID 221 /* d11 management WPA id */ ++#define DOT11_MNG_PROPR_ID 221 /* d11 management proprietary id */ ++/* should start using this one instead of above two */ ++#define DOT11_MNG_VS_ID 221 /* d11 management Vendor Specific IE */ ++ ++/* Rate element Basic flag and rate mask */ ++#define DOT11_RATE_BASIC 0x80 /* flag for a Basic Rate */ ++#define DOT11_RATE_MASK 0x7F /* mask for numeric part of rate */ ++ ++/* ERP info element bit values */ ++#define DOT11_MNG_ERP_LEN 1 /* ERP is currently 1 byte long */ ++#define DOT11_MNG_NONERP_PRESENT 0x01 /* NonERP (802.11b) STAs are present ++ *in the BSS ++ */ ++#define DOT11_MNG_USE_PROTECTION 0x02 /* Use protection mechanisms for ++ *ERP-OFDM frames ++ */ ++#define DOT11_MNG_BARKER_PREAMBLE 0x04 /* Short Preambles: 0 == allowed, ++ * 1 == not allowed ++ */ ++/* TS Delay element offset & size */ ++#define DOT11_MGN_TS_DELAY_LEN 4 /* length of TS DELAY IE */ ++#define TS_DELAY_FIELD_SIZE 4 /* TS DELAY field size */ ++ ++/* Capability Information Field */ ++#define DOT11_CAP_ESS 0x0001 /* d11 cap. ESS */ ++#define DOT11_CAP_IBSS 0x0002 /* d11 cap. IBSS */ ++#define DOT11_CAP_POLLABLE 0x0004 /* d11 cap. pollable */ ++#define DOT11_CAP_POLL_RQ 0x0008 /* d11 cap. poll request */ ++#define DOT11_CAP_PRIVACY 0x0010 /* d11 cap. privacy */ ++#define DOT11_CAP_SHORT 0x0020 /* d11 cap. short */ ++#define DOT11_CAP_PBCC 0x0040 /* d11 cap. PBCC */ ++#define DOT11_CAP_AGILITY 0x0080 /* d11 cap. agility */ ++#define DOT11_CAP_SPECTRUM 0x0100 /* d11 cap. spectrum */ ++#define DOT11_CAP_SHORTSLOT 0x0400 /* d11 cap. shortslot */ ++#define DOT11_CAP_RRM 0x1000 /* d11 cap. 11k radio measurement */ ++#define DOT11_CAP_CCK_OFDM 0x2000 /* d11 cap. CCK/OFDM */ ++ ++/* Extended capabilities IE bitfields */ ++/* 20/40 BSS Coexistence Management support bit position */ ++#define DOT11_EXT_CAP_OBSS_COEX_MGMT 0 ++/* scheduled PSMP support bit position */ ++#define DOT11_EXT_CAP_SPSMP 6 ++/* BSS Transition Management support bit position */ ++#define DOT11_EXT_CAP_BSS_TRANSITION_MGMT 19 ++/* Interworking support bit position */ ++#define DOT11_EXT_CAP_IW 31 ++/* service Interval granularity bit position and mask */ ++#define DOT11_EXT_CAP_SI 41 ++#define DOT11_EXT_CAP_SI_MASK 0x0E ++ ++/* ++ * Action Frame Constants ++ */ ++#define DOT11_ACTION_HDR_LEN 2 /* action frame category + action field */ ++#define DOT11_ACTION_CAT_OFF 0 /* category offset */ ++#define DOT11_ACTION_ACT_OFF 1 /* action offset */ ++ ++/* Action Category field (sec 7.3.1.11) */ ++#define DOT11_ACTION_CAT_ERR_MASK 0x80 /* category error mask */ ++#define DOT11_ACTION_CAT_MASK 0x7F /* category mask */ ++#define DOT11_ACTION_CAT_SPECT_MNG 0 /* category spectrum management */ ++#define DOT11_ACTION_CAT_QOS 1 /* category QoS */ ++#define DOT11_ACTION_CAT_DLS 2 /* category DLS */ ++#define DOT11_ACTION_CAT_BLOCKACK 3 /* category block ack */ ++#define DOT11_ACTION_CAT_PUBLIC 4 /* category public */ ++#define DOT11_ACTION_CAT_RRM 5 /* category radio measurements */ ++#define DOT11_ACTION_CAT_FBT 6 /* category fast bss transition */ ++#define DOT11_ACTION_CAT_HT 7 /* category for HT */ ++#define DOT11_ACTION_CAT_SA_QUERY 8 /* security association query */ ++#define DOT11_ACTION_CAT_PDPA 9 /* protected dual of public action */ ++#define DOT11_ACTION_CAT_BSSMGMT 10 /* category for BSS transition management */ ++#define DOT11_ACTION_NOTIFICATION 17 ++#define DOT11_ACTION_CAT_VSP 126 /* protected vendor specific */ ++#define DOT11_ACTION_CAT_VS 127 /* category Vendor Specific */ ++ ++/* Spectrum Management Action IDs (sec 7.4.1) */ ++#define DOT11_SM_ACTION_M_REQ 0 /* d11 action measurement request */ ++#define DOT11_SM_ACTION_M_REP 1 /* d11 action measurement response */ ++#define DOT11_SM_ACTION_TPC_REQ 2 /* d11 action TPC request */ ++#define DOT11_SM_ACTION_TPC_REP 3 /* d11 action TPC response */ ++#define DOT11_SM_ACTION_CHANNEL_SWITCH 4 /* d11 action channel switch */ ++#define DOT11_SM_ACTION_EXT_CSA 5 /* d11 extened CSA for 11n */ ++ ++/* HT action ids */ ++#define DOT11_ACTION_ID_HT_CH_WIDTH 0 /* notify channel width action id */ ++#define DOT11_ACTION_ID_HT_MIMO_PS 1 /* mimo ps action id */ ++ ++/* Public action ids */ ++#define DOT11_PUB_ACTION_BSS_COEX_MNG 0 /* 20/40 Coexistence Management action id */ ++#define DOT11_PUB_ACTION_CHANNEL_SWITCH 4 /* d11 action channel switch */ ++ ++/* Block Ack action types */ ++#define DOT11_BA_ACTION_ADDBA_REQ 0 /* ADDBA Req action frame type */ ++#define DOT11_BA_ACTION_ADDBA_RESP 1 /* ADDBA Resp action frame type */ ++#define DOT11_BA_ACTION_DELBA 2 /* DELBA action frame type */ ++ ++/* ADDBA action parameters */ ++#define DOT11_ADDBA_PARAM_AMSDU_SUP 0x0001 /* AMSDU supported under BA */ ++#define DOT11_ADDBA_PARAM_POLICY_MASK 0x0002 /* policy mask(ack vs delayed) */ ++#define DOT11_ADDBA_PARAM_POLICY_SHIFT 1 /* policy shift */ ++#define DOT11_ADDBA_PARAM_TID_MASK 0x003c /* tid mask */ ++#define DOT11_ADDBA_PARAM_TID_SHIFT 2 /* tid shift */ ++#define DOT11_ADDBA_PARAM_BSIZE_MASK 0xffc0 /* buffer size mask */ ++#define DOT11_ADDBA_PARAM_BSIZE_SHIFT 6 /* buffer size shift */ ++ ++#define DOT11_ADDBA_POLICY_DELAYED 0 /* delayed BA policy */ ++#define DOT11_ADDBA_POLICY_IMMEDIATE 1 /* immediate BA policy */ ++ ++/* Fast Transition action types */ ++#define DOT11_FT_ACTION_FT_RESERVED 0 ++#define DOT11_FT_ACTION_FT_REQ 1 /* FBT request - for over-the-DS FBT */ ++#define DOT11_FT_ACTION_FT_RES 2 /* FBT response - for over-the-DS FBT */ ++#define DOT11_FT_ACTION_FT_CON 3 /* FBT confirm - for OTDS with RRP */ ++#define DOT11_FT_ACTION_FT_ACK 4 /* FBT ack */ ++ ++/* DLS action types */ ++#define DOT11_DLS_ACTION_REQ 0 /* DLS Request */ ++#define DOT11_DLS_ACTION_RESP 1 /* DLS Response */ ++#define DOT11_DLS_ACTION_TD 2 /* DLS Teardown */ ++ ++/* Wireless Network Management (WNM) action types */ ++#define DOT11_WNM_ACTION_EVENT_REQ 0 ++#define DOT11_WNM_ACTION_EVENT_REP 1 ++#define DOT11_WNM_ACTION_DIAG_REQ 2 ++#define DOT11_WNM_ACTION_DIAG_REP 3 ++#define DOT11_WNM_ACTION_LOC_CFG_REQ 4 ++#define DOT11_WNM_ACTION_LOC_RFG_RESP 5 ++#define DOT11_WNM_ACTION_BSS_TRANS_QURY 6 ++#define DOT11_WNM_ACTION_BSS_TRANS_REQ 7 ++#define DOT11_WNM_ACTION_BSS_TRANS_RESP 8 ++#define DOT11_WNM_ACTION_FMS_REQ 9 ++#define DOT11_WNM_ACTION_FMS_RESP 10 ++#define DOT11_WNM_ACTION_COL_INTRFRNCE_REQ 11 ++#define DOT11_WNM_ACTION_COL_INTRFRNCE_REP 12 ++#define DOT11_WNM_ACTION_TFS_REQ 13 ++#define DOT11_WNM_ACTION_TFS_RESP 14 ++#define DOT11_WNM_ACTION_TFS_NOTIFY 15 ++#define DOT11_WNM_ACTION_WNM_SLEEP_REQ 16 ++#define DOT11_WNM_ACTION_WNM_SLEEP_RESP 17 ++#define DOT11_WNM_ACTION_TIM_BCAST_REQ 18 ++#define DOT11_WNM_ACTION_TIM_BCAST_RESP 19 ++#define DOT11_WNM_ACTION_QOS_TRFC_CAP_UPD 20 ++#define DOT11_WNM_ACTION_CHAN_USAGE_REQ 21 ++#define DOT11_WNM_ACTION_CHAN_USAGE_RESP 22 ++#define DOT11_WNM_ACTION_DMS_REQ 23 ++#define DOT11_WNM_ACTION_DMS_RESP 24 ++#define DOT11_WNM_ACTION_TMNG_MEASUR_REQ 25 ++#define DOT11_WNM_ACTION_NOTFCTN_REQ 26 ++#define DOT11_WNM_ACTION_NOTFCTN_RES 27 ++ ++#define DOT11_MNG_COUNTRY_ID_LEN 3 ++ ++/* DLS Request frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_dls_req { ++ uint8 category; /* category of action frame (2) */ ++ uint8 action; /* DLS action: req (0) */ ++ struct ether_addr da; /* destination address */ ++ struct ether_addr sa; /* source address */ ++ uint16 cap; /* capability */ ++ uint16 timeout; /* timeout value */ ++ uint8 data[1]; /* IE:support rate, extend support rate, HT cap */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_dls_req dot11_dls_req_t; ++#define DOT11_DLS_REQ_LEN 18 /* Fixed length */ ++ ++/* DLS response frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_dls_resp { ++ uint8 category; /* category of action frame (2) */ ++ uint8 action; /* DLS action: req (0) */ ++ uint16 status; /* status code field */ ++ struct ether_addr da; /* destination address */ ++ struct ether_addr sa; /* source address */ ++ uint8 data[1]; /* optional: capability, rate ... */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_dls_resp dot11_dls_resp_t; ++#define DOT11_DLS_RESP_LEN 16 /* Fixed length */ ++ ++ ++/* BSS Management Transition Query frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_bss_trans_query { ++ uint8 category; /* category of action frame (10) */ ++ uint8 action; /* WNM action: trans_query (6) */ ++ uint8 token; /* dialog token */ ++ uint8 reason; /* transition query reason */ ++ uint8 data[1]; /* Elements */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_bss_trans_query dot11_bss_trans_query_t; ++#define DOT11_BSS_TRANS_QUERY_LEN 4 /* Fixed length */ ++ ++/* BSS Management Transition Request frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_bss_trans_req { ++ uint8 category; /* category of action frame (10) */ ++ uint8 action; /* WNM action: trans_req (7) */ ++ uint8 token; /* dialog token */ ++ uint8 reqmode; /* transition request mode */ ++ uint16 disassoc_tmr; /* disassociation timer */ ++ uint8 validity_intrvl; /* validity interval */ ++ uint8 data[1]; /* optional: BSS term duration, ... */ ++ /* ...session info URL, list */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_bss_trans_req dot11_bss_trans_req_t; ++#define DOT11_BSS_TRANS_REQ_LEN 7 /* Fixed length */ ++ ++#define DOT11_BSS_TERM_DUR_LEN 12 /* Fixed length if present */ ++ ++ ++/* BSS Mgmt Transition Request Mode Field - 802.11v */ ++#define DOT11_BSS_TRNS_REQMODE_PREF_LIST_INCL 0x01 ++#define DOT11_BSS_TRNS_REQMODE_ABRIDGED 0x02 ++#define DOT11_BSS_TRNS_REQMODE_DISASSOC_IMMINENT 0x04 ++#define DOT11_BSS_TRNS_REQMODE_BSS_TERM_INCL 0x08 ++#define DOT11_BSS_TRNS_REQMODE_ESS_DISASSOC_IMNT 0x10 ++ ++ ++/* BSS Management transition response frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_bss_trans_res { ++ uint8 category; /* category of action frame (10) */ ++ uint8 action; /* WNM action: trans_res (8) */ ++ uint8 token; /* dialog token */ ++ uint8 status; /* transition status */ ++ uint8 term_delay; /* validity interval */ ++ uint8 data[1]; /* optional: BSS term duration, ... */ ++ /* ...session info URL, list */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_bss_trans_res dot11_bss_trans_res_t; ++#define DOT11_BSS_TRANS_RES_LEN 5 /* Fixed length */ ++ ++/* BSS Mgmt Transition Response Status Field */ ++#define DOT11_BSS_TRNS_RES_STATUS_ACCEPT 0 ++#define DOT11_BSS_TRNS_RES_STATUS_REJECT 1 ++#define DOT11_BSS_TRNS_RES_STATUS_REJ_INSUFF_BCN 2 ++#define DOT11_BSS_TRNS_RES_STATUS_REJ_INSUFF_CAP 3 ++#define DOT11_BSS_TRNS_RES_STATUS_REJ_TERM_UNDESIRED 4 ++#define DOT11_BSS_TRNS_RES_STATUS_REJ_TERM_DELAY_REQ 5 ++#define DOT11_BSS_TRNS_RES_STATUS_REJ_BSS_LIST_PROVIDED 6 ++#define DOT11_BSS_TRNS_RES_STATUS_REJ_NO_SUITABLE_BSS 7 ++#define DOT11_BSS_TRNS_RES_STATUS_REJ_LEAVING_ESS 8 ++ ++ ++/* Neighbor Report BSSID Information Field */ ++#define DOT11_NBR_RPRT_BSSID_INFO_REACHABILTY 0x0003 ++#define DOT11_NBR_RPRT_BSSID_INFO_SEC 0x0004 ++#define DOT11_NBR_RPRT_BSSID_INFO_KEY_SCOPE 0x0008 ++#define DOT11_NBR_RPRT_BSSID_INFO_CAP 0x03f0 ++ ++#define DOT11_NBR_RPRT_BSSID_INFO_CAP_SPEC_MGMT 0x0010 ++#define DOT11_NBR_RPRT_BSSID_INFO_CAP_QOS 0x0020 ++#define DOT11_NBR_RPRT_BSSID_INFO_CAP_APSD 0x0040 ++#define DOT11_NBR_RPRT_BSSID_INFO_CAP_RDIO_MSMT 0x0080 ++#define DOT11_NBR_RPRT_BSSID_INFO_CAP_DEL_BA 0x0100 ++#define DOT11_NBR_RPRT_BSSID_INFO_CAP_IMM_BA 0x0200 ++ ++/* Neighbor Report Subelements */ ++#define DOT11_NBR_RPRT_SUBELEM_BSS_CANDDT_PREF_ID 3 ++ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_addba_req { ++ uint8 category; /* category of action frame (3) */ ++ uint8 action; /* action: addba req */ ++ uint8 token; /* identifier */ ++ uint16 addba_param_set; /* parameter set */ ++ uint16 timeout; /* timeout in seconds */ ++ uint16 start_seqnum; /* starting sequence number */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_addba_req dot11_addba_req_t; ++#define DOT11_ADDBA_REQ_LEN 9 /* length of addba req frame */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_addba_resp { ++ uint8 category; /* category of action frame (3) */ ++ uint8 action; /* action: addba resp */ ++ uint8 token; /* identifier */ ++ uint16 status; /* status of add request */ ++ uint16 addba_param_set; /* negotiated parameter set */ ++ uint16 timeout; /* negotiated timeout in seconds */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_addba_resp dot11_addba_resp_t; ++#define DOT11_ADDBA_RESP_LEN 9 /* length of addba resp frame */ ++ ++/* DELBA action parameters */ ++#define DOT11_DELBA_PARAM_INIT_MASK 0x0800 /* initiator mask */ ++#define DOT11_DELBA_PARAM_INIT_SHIFT 11 /* initiator shift */ ++#define DOT11_DELBA_PARAM_TID_MASK 0xf000 /* tid mask */ ++#define DOT11_DELBA_PARAM_TID_SHIFT 12 /* tid shift */ ++ ++BWL_PRE_PACKED_STRUCT struct dot11_delba { ++ uint8 category; /* category of action frame (3) */ ++ uint8 action; /* action: addba req */ ++ uint16 delba_param_set; /* paarmeter set */ ++ uint16 reason; /* reason for dellba */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_delba dot11_delba_t; ++#define DOT11_DELBA_LEN 6 /* length of delba frame */ ++ ++/* SA Query action field value */ ++#define SA_QUERY_REQUEST 0 ++#define SA_QUERY_RESPONSE 1 ++ ++/* ************* 802.11r related definitions. ************* */ ++ ++/* Over-the-DS Fast Transition Request frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_ft_req { ++ uint8 category; /* category of action frame (6) */ ++ uint8 action; /* action: ft req */ ++ uint8 sta_addr[ETHER_ADDR_LEN]; ++ uint8 tgt_ap_addr[ETHER_ADDR_LEN]; ++ uint8 data[1]; /* Elements */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_ft_req dot11_ft_req_t; ++#define DOT11_FT_REQ_FIXED_LEN 14 ++ ++/* Over-the-DS Fast Transition Response frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_ft_res { ++ uint8 category; /* category of action frame (6) */ ++ uint8 action; /* action: ft resp */ ++ uint8 sta_addr[ETHER_ADDR_LEN]; ++ uint8 tgt_ap_addr[ETHER_ADDR_LEN]; ++ uint16 status; /* status code */ ++ uint8 data[1]; /* Elements */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_ft_res dot11_ft_res_t; ++#define DOT11_FT_RES_FIXED_LEN 16 ++ ++ ++/* ************* 802.11k related definitions. ************* */ ++ ++/* Radio measurements enabled capability ie */ ++ ++#define DOT11_RRM_CAP_LEN 5 /* length of rrm cap bitmap */ ++BWL_PRE_PACKED_STRUCT struct dot11_rrm_cap_ie { ++ uint8 cap[DOT11_RRM_CAP_LEN]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_rrm_cap_ie dot11_rrm_cap_ie_t; ++ ++/* Bitmap definitions for cap ie */ ++#define DOT11_RRM_CAP_LINK 0 ++#define DOT11_RRM_CAP_NEIGHBOR_REPORT 1 ++#define DOT11_RRM_CAP_PARALLEL 2 ++#define DOT11_RRM_CAP_REPEATED 3 ++#define DOT11_RRM_CAP_BCN_PASSIVE 4 ++#define DOT11_RRM_CAP_BCN_ACTIVE 5 ++#define DOT11_RRM_CAP_BCN_TABLE 6 ++#define DOT11_RRM_CAP_BCN_REP_COND 7 ++#define DOT11_RRM_CAP_AP_CHANREP 16 ++ ++ ++/* Operating Class (formerly "Regulatory Class") definitions */ ++#define DOT11_OP_CLASS_NONE 255 ++ ++ ++/* Radio Measurements action ids */ ++#define DOT11_RM_ACTION_RM_REQ 0 /* Radio measurement request */ ++#define DOT11_RM_ACTION_RM_REP 1 /* Radio measurement report */ ++#define DOT11_RM_ACTION_LM_REQ 2 /* Link measurement request */ ++#define DOT11_RM_ACTION_LM_REP 3 /* Link measurement report */ ++#define DOT11_RM_ACTION_NR_REQ 4 /* Neighbor report request */ ++#define DOT11_RM_ACTION_NR_REP 5 /* Neighbor report response */ ++ ++/* Generic radio measurement action frame header */ ++BWL_PRE_PACKED_STRUCT struct dot11_rm_action { ++ uint8 category; /* category of action frame (5) */ ++ uint8 action; /* radio measurement action */ ++ uint8 token; /* dialog token */ ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_rm_action dot11_rm_action_t; ++#define DOT11_RM_ACTION_LEN 3 ++ ++BWL_PRE_PACKED_STRUCT struct dot11_rmreq { ++ uint8 category; /* category of action frame (5) */ ++ uint8 action; /* radio measurement action */ ++ uint8 token; /* dialog token */ ++ uint16 reps; /* no. of repetitions */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_rmreq dot11_rmreq_t; ++#define DOT11_RMREQ_LEN 5 ++ ++BWL_PRE_PACKED_STRUCT struct dot11_rm_ie { ++ uint8 id; ++ uint8 len; ++ uint8 token; ++ uint8 mode; ++ uint8 type; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_rm_ie dot11_rm_ie_t; ++#define DOT11_RM_IE_LEN 5 ++ ++/* Definitions for "mode" bits in rm req */ ++#define DOT11_RMREQ_MODE_PARALLEL 1 ++#define DOT11_RMREQ_MODE_ENABLE 2 ++#define DOT11_RMREQ_MODE_REQUEST 4 ++#define DOT11_RMREQ_MODE_REPORT 8 ++#define DOT11_RMREQ_MODE_DURMAND 0x10 /* Duration Mandatory */ ++ ++/* Definitions for "mode" bits in rm rep */ ++#define DOT11_RMREP_MODE_LATE 1 ++#define DOT11_RMREP_MODE_INCAPABLE 2 ++#define DOT11_RMREP_MODE_REFUSED 4 ++ ++BWL_PRE_PACKED_STRUCT struct dot11_rmreq_bcn { ++ uint8 id; ++ uint8 len; ++ uint8 token; ++ uint8 mode; ++ uint8 type; ++ uint8 reg; ++ uint8 channel; ++ uint16 interval; ++ uint16 duration; ++ uint8 bcn_mode; ++ struct ether_addr bssid; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_rmreq_bcn dot11_rmreq_bcn_t; ++#define DOT11_RMREQ_BCN_LEN 18 ++ ++BWL_PRE_PACKED_STRUCT struct dot11_rmrep_bcn { ++ uint8 reg; ++ uint8 channel; ++ uint32 starttime[2]; ++ uint16 duration; ++ uint8 frame_info; ++ uint8 rcpi; ++ uint8 rsni; ++ struct ether_addr bssid; ++ uint8 antenna_id; ++ uint32 parent_tsf; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_rmrep_bcn dot11_rmrep_bcn_t; ++#define DOT11_RMREP_BCN_LEN 26 ++ ++/* Beacon request measurement mode */ ++#define DOT11_RMREQ_BCN_PASSIVE 0 ++#define DOT11_RMREQ_BCN_ACTIVE 1 ++#define DOT11_RMREQ_BCN_TABLE 2 ++ ++/* Sub-element IDs for Beacon Request */ ++#define DOT11_RMREQ_BCN_SSID_ID 0 ++#define DOT11_RMREQ_BCN_REPINFO_ID 1 ++#define DOT11_RMREQ_BCN_REPDET_ID 2 ++#define DOT11_RMREQ_BCN_REQUEST_ID 10 ++#define DOT11_RMREQ_BCN_APCHREP_ID 51 ++ ++/* Reporting Detail element definition */ ++#define DOT11_RMREQ_BCN_REPDET_FIXED 0 /* Fixed length fields only */ ++#define DOT11_RMREQ_BCN_REPDET_REQUEST 1 /* + requested information elems */ ++#define DOT11_RMREQ_BCN_REPDET_ALL 2 /* All fields */ ++ ++/* Sub-element IDs for Beacon Report */ ++#define DOT11_RMREP_BCN_FRM_BODY 1 ++ ++/* Neighbor measurement report */ ++BWL_PRE_PACKED_STRUCT struct dot11_rmrep_nbr { ++ struct ether_addr bssid; ++ uint32 bssid_info; ++ uint8 reg; ++ uint8 channel; ++ uint8 phytype; ++ uchar sub_elements[1]; /* Variable size data */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_rmrep_nbr dot11_rmrep_nbr_t; ++#define DOT11_RMREP_NBR_LEN 13 ++ ++/* MLME Enumerations */ ++#define DOT11_BSSTYPE_INFRASTRUCTURE 0 /* d11 infrastructure */ ++#define DOT11_BSSTYPE_INDEPENDENT 1 /* d11 independent */ ++#define DOT11_BSSTYPE_ANY 2 /* d11 any BSS type */ ++#define DOT11_SCANTYPE_ACTIVE 0 /* d11 scan active */ ++#define DOT11_SCANTYPE_PASSIVE 1 /* d11 scan passive */ ++ ++/* Link Measurement */ ++BWL_PRE_PACKED_STRUCT struct dot11_lmreq { ++ uint8 category; /* category of action frame (5) */ ++ uint8 action; /* radio measurement action */ ++ uint8 token; /* dialog token */ ++ uint8 txpwr; /* Transmit Power Used */ ++ uint8 maxtxpwr; /* Max Transmit Power */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_lmreq dot11_lmreq_t; ++#define DOT11_LMREQ_LEN 5 ++ ++BWL_PRE_PACKED_STRUCT struct dot11_lmrep { ++ uint8 category; /* category of action frame (5) */ ++ uint8 action; /* radio measurement action */ ++ uint8 token; /* dialog token */ ++ dot11_tpc_rep_t tpc; /* TPC element */ ++ uint8 rxant; /* Receive Antenna ID */ ++ uint8 txant; /* Transmit Antenna ID */ ++ uint8 rcpi; /* RCPI */ ++ uint8 rsni; /* RSNI */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_lmrep dot11_lmrep_t; ++#define DOT11_LMREP_LEN 11 ++ ++/* 802.11 BRCM "Compromise" Pre N constants */ ++#define PREN_PREAMBLE 24 /* green field preamble time */ ++#define PREN_MM_EXT 12 /* extra mixed mode preamble time */ ++#define PREN_PREAMBLE_EXT 4 /* extra preamble (multiply by unique_streams-1) */ ++ ++/* 802.11N PHY constants */ ++#define RIFS_11N_TIME 2 /* NPHY RIFS time */ ++ ++/* 802.11 HT PLCP format 802.11n-2009, sec 20.3.9.4.3 ++ * HT-SIG is composed of two 24 bit parts, HT-SIG1 and HT-SIG2 ++ */ ++/* HT-SIG1 */ ++#define HT_SIG1_MCS_MASK 0x00007F ++#define HT_SIG1_CBW 0x000080 ++#define HT_SIG1_HT_LENGTH 0xFFFF00 ++ ++/* HT-SIG2 */ ++#define HT_SIG2_SMOOTHING 0x000001 ++#define HT_SIG2_NOT_SOUNDING 0x000002 ++#define HT_SIG2_RESERVED 0x000004 ++#define HT_SIG2_AGGREGATION 0x000008 ++#define HT_SIG2_STBC_MASK 0x000030 ++#define HT_SIG2_STBC_SHIFT 4 ++#define HT_SIG2_FEC_CODING 0x000040 ++#define HT_SIG2_SHORT_GI 0x000080 ++#define HT_SIG2_ESS_MASK 0x000300 ++#define HT_SIG2_ESS_SHIFT 8 ++#define HT_SIG2_CRC 0x03FC00 ++#define HT_SIG2_TAIL 0x1C0000 ++ ++/* 802.11 A PHY constants */ ++#define APHY_SLOT_TIME 9 /* APHY slot time */ ++#define APHY_SIFS_TIME 16 /* APHY SIFS time */ ++#define APHY_DIFS_TIME (APHY_SIFS_TIME + (2 * APHY_SLOT_TIME)) /* APHY DIFS time */ ++#define APHY_PREAMBLE_TIME 16 /* APHY preamble time */ ++#define APHY_SIGNAL_TIME 4 /* APHY signal time */ ++#define APHY_SYMBOL_TIME 4 /* APHY symbol time */ ++#define APHY_SERVICE_NBITS 16 /* APHY service nbits */ ++#define APHY_TAIL_NBITS 6 /* APHY tail nbits */ ++#define APHY_CWMIN 15 /* APHY cwmin */ ++ ++/* 802.11 B PHY constants */ ++#define BPHY_SLOT_TIME 20 /* BPHY slot time */ ++#define BPHY_SIFS_TIME 10 /* BPHY SIFS time */ ++#define BPHY_DIFS_TIME 50 /* BPHY DIFS time */ ++#define BPHY_PLCP_TIME 192 /* BPHY PLCP time */ ++#define BPHY_PLCP_SHORT_TIME 96 /* BPHY PLCP short time */ ++#define BPHY_CWMIN 31 /* BPHY cwmin */ ++ ++/* 802.11 G constants */ ++#define DOT11_OFDM_SIGNAL_EXTENSION 6 /* d11 OFDM signal extension */ ++ ++#define PHY_CWMAX 1023 /* PHY cwmax */ ++ ++#define DOT11_MAXNUMFRAGS 16 /* max # fragments per MSDU */ ++ ++/* 802.11 AC (VHT) constants */ ++ ++typedef int vht_group_id_t; ++ ++/* for VHT-A1 */ ++/* SIG-A1 reserved bits */ ++#define VHT_SIGA1_CONST_MASK 0x800004 ++ ++#define VHT_SIGA1_20MHZ_VAL 0x000000 ++#define VHT_SIGA1_40MHZ_VAL 0x000001 ++#define VHT_SIGA1_80MHZ_VAL 0x000002 ++#define VHT_SIGA1_160MHZ_VAL 0x000003 ++ ++#define VHT_SIGA1_STBC 0x000008 ++ ++#define VHT_SIGA1_GID_MAX_GID 0x3f ++#define VHT_SIGA1_GID_SHIFT 4 ++#define VHT_SIGA1_GID_TO_AP 0x00 ++#define VHT_SIGA1_GID_NOT_TO_AP 0x3f ++ ++#define VHT_SIGA1_NSTS_SHIFT 10 ++#define VHT_SIGA1_NSTS_SHIFT_MASK_USER0 0x001C00 ++ ++#define VHT_SIGA1_PARTIAL_AID_SHIFT 13 ++ ++/* for VHT-A2 */ ++#define VHT_SIGA2_GI_NONE 0x000000 ++#define VHT_SIGA2_GI_SHORT 0x000001 ++#define VHT_SIGA2_GI_W_MOD10 0x000002 ++#define VHT_SIGA2_CODING_LDPC 0x000004 ++#define VHT_SIGA2_BEAMFORM_ENABLE 0x000100 ++#define VHT_SIGA2_MCS_SHIFT 4 ++ ++#define VHT_SIGA2_B9_RESERVED 0x000200 ++#define VHT_SIGA2_TAIL_MASK 0xfc0000 ++#define VHT_SIGA2_TAIL_VALUE 0x000000 ++ ++#define VHT_SIGA2_SVC_BITS 16 ++#define VHT_SIGA2_TAIL_BITS 6 ++ ++ ++/* dot11Counters Table - 802.11 spec., Annex D */ ++typedef struct d11cnt { ++ uint32 txfrag; /* dot11TransmittedFragmentCount */ ++ uint32 txmulti; /* dot11MulticastTransmittedFrameCount */ ++ uint32 txfail; /* dot11FailedCount */ ++ uint32 txretry; /* dot11RetryCount */ ++ uint32 txretrie; /* dot11MultipleRetryCount */ ++ uint32 rxdup; /* dot11FrameduplicateCount */ ++ uint32 txrts; /* dot11RTSSuccessCount */ ++ uint32 txnocts; /* dot11RTSFailureCount */ ++ uint32 txnoack; /* dot11ACKFailureCount */ ++ uint32 rxfrag; /* dot11ReceivedFragmentCount */ ++ uint32 rxmulti; /* dot11MulticastReceivedFrameCount */ ++ uint32 rxcrc; /* dot11FCSErrorCount */ ++ uint32 txfrmsnt; /* dot11TransmittedFrameCount */ ++ uint32 rxundec; /* dot11WEPUndecryptableCount */ ++} d11cnt_t; ++ ++/* OUI for BRCM proprietary IE */ ++#define BRCM_PROP_OUI "\x00\x90\x4C" /* Broadcom proprietary OUI */ ++ ++ ++/* BRCM OUI: Used in the proprietary(221) IE in all broadcom devices */ ++#define BRCM_OUI "\x00\x10\x18" /* Broadcom OUI */ ++ ++/* BRCM info element */ ++BWL_PRE_PACKED_STRUCT struct brcm_ie { ++ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */ ++ uint8 len; /* IE length */ ++ uint8 oui[3]; /* Proprietary OUI, BRCM_OUI */ ++ uint8 ver; /* type/ver of this IE */ ++ uint8 assoc; /* # of assoc STAs */ ++ uint8 flags; /* misc flags */ ++ uint8 flags1; /* misc flags */ ++ uint16 amsdu_mtu_pref; /* preferred A-MSDU MTU */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct brcm_ie brcm_ie_t; ++#define BRCM_IE_LEN 11 /* BRCM IE length */ ++#define BRCM_IE_VER 2 /* BRCM IE version */ ++#define BRCM_IE_LEGACY_AES_VER 1 /* BRCM IE legacy AES version */ ++ ++/* brcm_ie flags */ ++#define BRF_LZWDS 0x4 /* lazy wds enabled */ ++#define BRF_BLOCKACK 0x8 /* BlockACK capable */ ++ ++/* brcm_ie flags1 */ ++#define BRF1_AMSDU 0x1 /* A-MSDU capable */ ++#define BRF1_WMEPS 0x4 /* AP is capable of handling WME + PS w/o APSD */ ++#define BRF1_PSOFIX 0x8 /* AP has fixed PS mode out-of-order packets */ ++#define BRF1_RX_LARGE_AGG 0x10 /* device can rx large aggregates */ ++#define BRF1_RFAWARE_DCS 0x20 /* RFAWARE dynamic channel selection (DCS) */ ++#define BRF1_SOFTAP 0x40 /* Configure as Broadcom SOFTAP */ ++ ++/* Vendor IE structure */ ++BWL_PRE_PACKED_STRUCT struct vndr_ie { ++ uchar id; ++ uchar len; ++ uchar oui [3]; ++ uchar data [1]; /* Variable size data */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct vndr_ie vndr_ie_t; ++ ++#define VNDR_IE_HDR_LEN 2 /* id + len field */ ++#define VNDR_IE_MIN_LEN 3 /* size of the oui field */ ++#define VNDR_IE_FIXED_LEN (VNDR_IE_HDR_LEN + VNDR_IE_MIN_LEN) ++#define VNDR_IE_MAX_LEN 256 /* verdor IE max length */ ++ ++/* ************* HT definitions. ************* */ ++#define MCSSET_LEN 16 /* 16-bits per 8-bit set to give 128-bits bitmap of MCS Index */ ++#define MAX_MCS_NUM (128) /* max mcs number = 128 */ ++ ++BWL_PRE_PACKED_STRUCT struct ht_cap_ie { ++ uint16 cap; ++ uint8 params; ++ uint8 supp_mcs[MCSSET_LEN]; ++ uint16 ext_htcap; ++ uint32 txbf_cap; ++ uint8 as_cap; ++} BWL_POST_PACKED_STRUCT; ++typedef struct ht_cap_ie ht_cap_ie_t; ++ ++/* CAP IE: HT 1.0 spec. simply stole a 802.11 IE, we use our prop. IE until this is resolved */ ++/* the capability IE is primarily used to convey this nodes abilities */ ++BWL_PRE_PACKED_STRUCT struct ht_prop_cap_ie { ++ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */ ++ uint8 len; /* IE length */ ++ uint8 oui[3]; /* Proprietary OUI, BRCM_PROP_OUI */ ++ uint8 type; /* type inidicates what follows */ ++ ht_cap_ie_t cap_ie; ++} BWL_POST_PACKED_STRUCT; ++typedef struct ht_prop_cap_ie ht_prop_cap_ie_t; ++ ++#define HT_PROP_IE_OVERHEAD 4 /* overhead bytes for prop oui ie */ ++#define HT_CAP_IE_LEN 26 /* HT capability len (based on .11n d2.0) */ ++#define HT_CAP_IE_TYPE 51 ++ ++#define HT_CAP_LDPC_CODING 0x0001 /* Support for rx of LDPC coded pkts */ ++#define HT_CAP_40MHZ 0x0002 /* FALSE:20Mhz, TRUE:20/40MHZ supported */ ++#define HT_CAP_MIMO_PS_MASK 0x000C /* Mimo PS mask */ ++#define HT_CAP_MIMO_PS_SHIFT 0x0002 /* Mimo PS shift */ ++#define HT_CAP_MIMO_PS_OFF 0x0003 /* Mimo PS, no restriction */ ++#define HT_CAP_MIMO_PS_RTS 0x0001 /* Mimo PS, send RTS/CTS around MIMO frames */ ++#define HT_CAP_MIMO_PS_ON 0x0000 /* Mimo PS, MIMO disallowed */ ++#define HT_CAP_GF 0x0010 /* Greenfield preamble support */ ++#define HT_CAP_SHORT_GI_20 0x0020 /* 20MHZ short guard interval support */ ++#define HT_CAP_SHORT_GI_40 0x0040 /* 40Mhz short guard interval support */ ++#define HT_CAP_TX_STBC 0x0080 /* Tx STBC support */ ++#define HT_CAP_RX_STBC_MASK 0x0300 /* Rx STBC mask */ ++#define HT_CAP_RX_STBC_SHIFT 8 /* Rx STBC shift */ ++#define HT_CAP_DELAYED_BA 0x0400 /* delayed BA support */ ++#define HT_CAP_MAX_AMSDU 0x0800 /* Max AMSDU size in bytes , 0=3839, 1=7935 */ ++ ++#define HT_CAP_DSSS_CCK 0x1000 /* DSSS/CCK supported by the BSS */ ++#define HT_CAP_PSMP 0x2000 /* Power Save Multi Poll support */ ++#define HT_CAP_40MHZ_INTOLERANT 0x4000 /* 40MHz Intolerant */ ++#define HT_CAP_LSIG_TXOP 0x8000 /* L-SIG TXOP protection support */ ++ ++#define HT_CAP_RX_STBC_NO 0x0 /* no rx STBC support */ ++#define HT_CAP_RX_STBC_ONE_STREAM 0x1 /* rx STBC support of 1 spatial stream */ ++#define HT_CAP_RX_STBC_TWO_STREAM 0x2 /* rx STBC support of 1-2 spatial streams */ ++#define HT_CAP_RX_STBC_THREE_STREAM 0x3 /* rx STBC support of 1-3 spatial streams */ ++ ++#define VHT_MAX_MPDU 11454 /* max mpdu size for now (bytes) */ ++#define VHT_MPDU_MSDU_DELTA 56 /* Difference in spec - vht mpdu, amsdu len */ ++/* Max AMSDU len - per spec */ ++#define VHT_MAX_AMSDU (VHT_MAX_MPDU - VHT_MPDU_MSDU_DELTA) ++ ++#define HT_MAX_AMSDU 7935 /* max amsdu size (bytes) per the HT spec */ ++#define HT_MIN_AMSDU 3835 /* min amsdu size (bytes) per the HT spec */ ++ ++#define HT_PARAMS_RX_FACTOR_MASK 0x03 /* ampdu rcv factor mask */ ++#define HT_PARAMS_DENSITY_MASK 0x1C /* ampdu density mask */ ++#define HT_PARAMS_DENSITY_SHIFT 2 /* ampdu density shift */ ++ ++/* HT/AMPDU specific define */ ++#define AMPDU_MAX_MPDU_DENSITY 7 /* max mpdu density; in 1/4 usec units */ ++#define AMPDU_DENSITY_NONE 0 /* No density requirement */ ++#define AMPDU_DENSITY_1over4_US 1 /* 1/4 us density */ ++#define AMPDU_DENSITY_1over2_US 2 /* 1/2 us density */ ++#define AMPDU_DENSITY_1_US 3 /* 1 us density */ ++#define AMPDU_DENSITY_2_US 4 /* 2 us density */ ++#define AMPDU_DENSITY_4_US 5 /* 4 us density */ ++#define AMPDU_DENSITY_8_US 6 /* 8 us density */ ++#define AMPDU_DENSITY_16_US 7 /* 16 us density */ ++#define AMPDU_RX_FACTOR_8K 0 /* max rcv ampdu len (8kb) */ ++#define AMPDU_RX_FACTOR_16K 1 /* max rcv ampdu len (16kb) */ ++#define AMPDU_RX_FACTOR_32K 2 /* max rcv ampdu len (32kb) */ ++#define AMPDU_RX_FACTOR_64K 3 /* max rcv ampdu len (64kb) */ ++#define AMPDU_RX_FACTOR_BASE 8*1024 /* ampdu factor base for rx len */ ++ ++#define AMPDU_DELIMITER_LEN 4 /* length of ampdu delimiter */ ++#define AMPDU_DELIMITER_LEN_MAX 63 /* max length of ampdu delimiter(enforced in HW) */ ++ ++#define HT_CAP_EXT_PCO 0x0001 ++#define HT_CAP_EXT_PCO_TTIME_MASK 0x0006 ++#define HT_CAP_EXT_PCO_TTIME_SHIFT 1 ++#define HT_CAP_EXT_MCS_FEEDBACK_MASK 0x0300 ++#define HT_CAP_EXT_MCS_FEEDBACK_SHIFT 8 ++#define HT_CAP_EXT_HTC 0x0400 ++#define HT_CAP_EXT_RD_RESP 0x0800 ++ ++BWL_PRE_PACKED_STRUCT struct ht_add_ie { ++ uint8 ctl_ch; /* control channel number */ ++ uint8 byte1; /* ext ch,rec. ch. width, RIFS support */ ++ uint16 opmode; /* operation mode */ ++ uint16 misc_bits; /* misc bits */ ++ uint8 basic_mcs[MCSSET_LEN]; /* required MCS set */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct ht_add_ie ht_add_ie_t; ++ ++/* ADD IE: HT 1.0 spec. simply stole a 802.11 IE, we use our prop. IE until this is resolved */ ++/* the additional IE is primarily used to convey the current BSS configuration */ ++BWL_PRE_PACKED_STRUCT struct ht_prop_add_ie { ++ uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */ ++ uint8 len; /* IE length */ ++ uint8 oui[3]; /* Proprietary OUI, BRCM_PROP_OUI */ ++ uint8 type; /* indicates what follows */ ++ ht_add_ie_t add_ie; ++} BWL_POST_PACKED_STRUCT; ++typedef struct ht_prop_add_ie ht_prop_add_ie_t; ++ ++#define HT_ADD_IE_LEN 22 ++#define HT_ADD_IE_TYPE 52 ++ ++/* byte1 defn's */ ++#define HT_BW_ANY 0x04 /* set, STA can use 20 or 40MHz */ ++#define HT_RIFS_PERMITTED 0x08 /* RIFS allowed */ ++ ++/* opmode defn's */ ++#define HT_OPMODE_MASK 0x0003 /* protection mode mask */ ++#define HT_OPMODE_SHIFT 0 /* protection mode shift */ ++#define HT_OPMODE_PURE 0x0000 /* protection mode PURE */ ++#define HT_OPMODE_OPTIONAL 0x0001 /* protection mode optional */ ++#define HT_OPMODE_HT20IN40 0x0002 /* protection mode 20MHz HT in 40MHz BSS */ ++#define HT_OPMODE_MIXED 0x0003 /* protection mode Mixed Mode */ ++#define HT_OPMODE_NONGF 0x0004 /* protection mode non-GF */ ++#define DOT11N_TXBURST 0x0008 /* Tx burst limit */ ++#define DOT11N_OBSS_NONHT 0x0010 /* OBSS Non-HT STA present */ ++ ++/* misc_bites defn's */ ++#define HT_BASIC_STBC_MCS 0x007f /* basic STBC MCS */ ++#define HT_DUAL_STBC_PROT 0x0080 /* Dual STBC Protection */ ++#define HT_SECOND_BCN 0x0100 /* Secondary beacon support */ ++#define HT_LSIG_TXOP 0x0200 /* L-SIG TXOP Protection full support */ ++#define HT_PCO_ACTIVE 0x0400 /* PCO active */ ++#define HT_PCO_PHASE 0x0800 /* PCO phase */ ++#define HT_DUALCTS_PROTECTION 0x0080 /* DUAL CTS protection needed */ ++ ++/* Tx Burst Limits */ ++#define DOT11N_2G_TXBURST_LIMIT 6160 /* 2G band Tx burst limit per 802.11n Draft 1.10 (usec) */ ++#define DOT11N_5G_TXBURST_LIMIT 3080 /* 5G band Tx burst limit per 802.11n Draft 1.10 (usec) */ ++ ++/* Macros for opmode */ ++#define GET_HT_OPMODE(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \ ++ >> HT_OPMODE_SHIFT) ++#define HT_MIXEDMODE_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \ ++ == HT_OPMODE_MIXED) /* mixed mode present */ ++#define HT_HT20_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \ ++ == HT_OPMODE_HT20IN40) /* 20MHz HT present */ ++#define HT_OPTIONAL_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \ ++ == HT_OPMODE_OPTIONAL) /* Optional protection present */ ++#define HT_USE_PROTECTION(add_ie) (HT_HT20_PRESENT((add_ie)) || \ ++ HT_MIXEDMODE_PRESENT((add_ie))) /* use protection */ ++#define HT_NONGF_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_NONGF) \ ++ == HT_OPMODE_NONGF) /* non-GF present */ ++#define DOT11N_TXBURST_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & DOT11N_TXBURST) \ ++ == DOT11N_TXBURST) /* Tx Burst present */ ++#define DOT11N_OBSS_NONHT_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & DOT11N_OBSS_NONHT) \ ++ == DOT11N_OBSS_NONHT) /* OBSS Non-HT present */ ++ ++BWL_PRE_PACKED_STRUCT struct obss_params { ++ uint16 passive_dwell; ++ uint16 active_dwell; ++ uint16 bss_widthscan_interval; ++ uint16 passive_total; ++ uint16 active_total; ++ uint16 chanwidth_transition_dly; ++ uint16 activity_threshold; ++} BWL_POST_PACKED_STRUCT; ++typedef struct obss_params obss_params_t; ++ ++BWL_PRE_PACKED_STRUCT struct dot11_obss_ie { ++ uint8 id; ++ uint8 len; ++ obss_params_t obss_params; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_obss_ie dot11_obss_ie_t; ++#define DOT11_OBSS_SCAN_IE_LEN sizeof(obss_params_t) /* HT OBSS len (based on 802.11n d3.0) */ ++ ++/* HT control field */ ++#define HT_CTRL_LA_TRQ 0x00000002 /* sounding request */ ++#define HT_CTRL_LA_MAI 0x0000003C /* MCS request or antenna selection indication */ ++#define HT_CTRL_LA_MAI_SHIFT 2 ++#define HT_CTRL_LA_MAI_MRQ 0x00000004 /* MCS request */ ++#define HT_CTRL_LA_MAI_MSI 0x00000038 /* MCS request sequence identifier */ ++#define HT_CTRL_LA_MFSI 0x000001C0 /* MFB sequence identifier */ ++#define HT_CTRL_LA_MFSI_SHIFT 6 ++#define HT_CTRL_LA_MFB_ASELC 0x0000FE00 /* MCS feedback, antenna selection command/data */ ++#define HT_CTRL_LA_MFB_ASELC_SH 9 ++#define HT_CTRL_LA_ASELC_CMD 0x00000C00 /* ASEL command */ ++#define HT_CTRL_LA_ASELC_DATA 0x0000F000 /* ASEL data */ ++#define HT_CTRL_CAL_POS 0x00030000 /* Calibration position */ ++#define HT_CTRL_CAL_SEQ 0x000C0000 /* Calibration sequence */ ++#define HT_CTRL_CSI_STEERING 0x00C00000 /* CSI/Steering */ ++#define HT_CTRL_CSI_STEER_SHIFT 22 ++#define HT_CTRL_CSI_STEER_NFB 0 /* no fedback required */ ++#define HT_CTRL_CSI_STEER_CSI 1 /* CSI, H matrix */ ++#define HT_CTRL_CSI_STEER_NCOM 2 /* non-compressed beamforming */ ++#define HT_CTRL_CSI_STEER_COM 3 /* compressed beamforming */ ++#define HT_CTRL_NDP_ANNOUNCE 0x01000000 /* NDP announcement */ ++#define HT_CTRL_AC_CONSTRAINT 0x40000000 /* AC Constraint */ ++#define HT_CTRL_RDG_MOREPPDU 0x80000000 /* RDG/More PPDU */ ++ ++#define HT_OPMODE_OPTIONAL 0x0001 /* protection mode optional */ ++#define HT_OPMODE_HT20IN40 0x0002 /* protection mode 20MHz HT in 40MHz BSS */ ++#define HT_OPMODE_MIXED 0x0003 /* protection mode Mixed Mode */ ++#define HT_OPMODE_NONGF 0x0004 /* protection mode non-GF */ ++#define DOT11N_TXBURST 0x0008 /* Tx burst limit */ ++#define DOT11N_OBSS_NONHT 0x0010 /* OBSS Non-HT STA present */ ++ ++/* ************* VHT definitions. ************* */ ++ ++BWL_PRE_PACKED_STRUCT struct vht_cap_ie { ++ uint32 vht_cap_info; ++ /* supported MCS set - 64 bit field */ ++ uint16 rx_mcs_map; ++ uint16 rx_max_rate; ++ uint16 tx_mcs_map; ++ uint16 tx_max_rate; ++} BWL_POST_PACKED_STRUCT; ++typedef struct vht_cap_ie vht_cap_ie_t; ++/* 4B cap_info + 8B supp_mcs */ ++#define VHT_CAP_IE_LEN 12 ++/* 32bit - cap info */ ++#define VHT_CAP_INFO_MAX_MPDU_LEN_MASK 0x00000003 ++#define VHT_CAP_INFO_SUPP_CHAN_WIDTH_MASK 0x0000000c ++#define VHT_CAP_INFO_LDPC 0x00000010 ++#define VHT_CAP_INFO_SGI_80MHZ 0x00000020 ++ ++#define VHT_CAP_INFO_SGI_160MHZ 0x00000040 ++#define VHT_CAP_INFO_TX_STBC 0x00000080 ++ ++#define VHT_CAP_INFO_RX_STBC_MASK 0x00000700 ++#define VHT_CAP_INFO_RX_STBC_SHIFT 8 ++#define VHT_CAP_INFO_SU_BEAMFMR 0x00000800 ++#define VHT_CAP_INFO_SU_BEAMFMEE 0x00001000 ++#define VHT_CAP_INFO_NUM_BMFMR_ANT_MASK 0x0000e000 ++#define VHT_CAP_INFO_NUM_BMFMR_ANT_SHIFT 13 ++ ++#define VHT_CAP_INFO_NUM_SOUNDING_DIM_MASK 0x00070000 ++#define VHT_CAP_INFO_NUM_SOUNDING_DIM_SHIFT 16 ++#define VHT_CAP_INFO_MU_BEAMFMR 0x00080000 ++#define VHT_CAP_INFO_MU_BEAMFMEE 0x00100000 ++#define VHT_CAP_INFO_TXOPPS 0x00200000 ++#define VHT_CAP_INFO_HTCVHT 0x00400000 ++#define VHT_CAP_INFO_AMPDU_MAXLEN_EXP_MASK 0x03800000 ++#define VHT_CAP_INFO_AMPDU_MAXLEN_EXP_SHIFT 23 ++ ++#define VHT_CAP_INFO_LINK_ADAPT_CAP_MASK 0x0c000000 ++#define VHT_CAP_INFO_LINK_ADAPT_CAP_SHIFT 26 ++ ++/* 64-bit Supp MCS. */ ++#define VHT_CAP_SUPP_MCS_RX_HIGHEST_RATE_MASK 0x1fff ++#define VHT_CAP_SUPP_MCS_RX_HIGHEST_RATE_SHIFT 0 ++ ++#define VHT_CAP_SUPP_MCS_TX_HIGHEST_RATE_MASK 0x1fff ++#define VHT_CAP_SUPP_MCS_TX_HIGHEST_RATE_SHIFT 0 ++ ++#define VHT_CAP_MCS_MAP_0_7 0 ++#define VHT_CAP_MCS_MAP_0_8 1 ++#define VHT_CAP_MCS_MAP_0_9 2 ++#define VHT_CAP_MCS_MAP_NONE 3 ++ ++#define VHT_CAP_MCS_MAP_NSS_MAX 8 ++ ++/* VHT Capabilities Supported Channel Width */ ++typedef enum vht_cap_chan_width { ++ VHT_CAP_CHAN_WIDTH_20_40 = 0x00, ++ VHT_CAP_CHAN_WIDTH_80 = 0x04, ++ VHT_CAP_CHAN_WIDTH_160 = 0x08 ++} vht_cap_chan_width_t; ++ ++/* VHT Capabilities Supported max MPDU LEN */ ++typedef enum vht_cap_max_mpdu_len { ++ VHT_CAP_MPDU_MAX_4K = 0x00, ++ VHT_CAP_MPDU_MAX_8K = 0x01, ++ VHT_CAP_MPDU_MAX_11K = 0x02 ++} vht_cap_max_mpdu_len_t; ++ ++/* VHT Operation Element */ ++BWL_PRE_PACKED_STRUCT struct vht_op_ie { ++ uint8 chan_width; ++ uint8 chan1; ++ uint8 chan2; ++ uint16 supp_mcs; /* same def as above in vht cap */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct vht_op_ie vht_op_ie_t; ++/* 3B VHT Op info + 2B Basic MCS */ ++#define VHT_OP_IE_LEN 5 ++ ++typedef enum vht_op_chan_width { ++ VHT_OP_CHAN_WIDTH_20_40 = 0, ++ VHT_OP_CHAN_WIDTH_80 = 1, ++ VHT_OP_CHAN_WIDTH_160 = 2, ++ VHT_OP_CHAN_WIDTH_80_80 = 3 ++} vht_op_chan_width_t; ++ ++/* Def for rx & tx basic mcs maps - ea ss num has 2 bits of info */ ++#define VHT_MCS_MAP_GET_SS_IDX(nss) (((nss)-1)*2) ++#define VHT_MCS_MAP_GET_MCS_PER_SS(nss, mcsMap) \ ++ (((mcsMap) >> VHT_MCS_MAP_GET_SS_IDX(nss)) & 0x3) ++#define VHT_MCS_MAP_SET_MCS_PER_SS(nss, numMcs, mcsMap) \ ++ ((mcsMap) |= (((numMcs) & 0x3) << VHT_MCS_MAP_GET_SS_IDX(nss))) ++ ++/* ************* WPA definitions. ************* */ ++#define WPA_OUI "\x00\x50\xF2" /* WPA OUI */ ++#define WPA_OUI_LEN 3 /* WPA OUI length */ ++#define WPA_OUI_TYPE 1 ++#define WPA_VERSION 1 /* WPA version */ ++#define WPA2_OUI "\x00\x0F\xAC" /* WPA2 OUI */ ++#define WPA2_OUI_LEN 3 /* WPA2 OUI length */ ++#define WPA2_VERSION 1 /* WPA2 version */ ++#define WPA2_VERSION_LEN 2 /* WAP2 version length */ ++ ++/* ************* WPS definitions. ************* */ ++#define WPS_OUI "\x00\x50\xF2" /* WPS OUI */ ++#define WPS_OUI_LEN 3 /* WPS OUI length */ ++#define WPS_OUI_TYPE 4 ++ ++/* ************* WFA definitions. ************* */ ++ ++#ifdef P2P_IE_OVRD ++#define WFA_OUI MAC_OUI ++#else ++#define WFA_OUI "\x50\x6F\x9A" /* WFA OUI */ ++#endif /* P2P_IE_OVRD */ ++#define WFA_OUI_LEN 3 /* WFA OUI length */ ++#ifdef P2P_IE_OVRD ++#define WFA_OUI_TYPE_P2P MAC_OUI_TYPE_P2P ++#else ++#define WFA_OUI_TYPE_P2P 9 ++#endif ++ ++#define WFA_OUI_TYPE_TPC 8 ++#ifdef WLTDLS ++#define WFA_OUI_TYPE_WFD 10 ++#endif /* WTDLS */ ++ ++/* RSN authenticated key managment suite */ ++#define RSN_AKM_NONE 0 /* None (IBSS) */ ++#define RSN_AKM_UNSPECIFIED 1 /* Over 802.1x */ ++#define RSN_AKM_PSK 2 /* Pre-shared Key */ ++#define RSN_AKM_FBT_1X 3 /* Fast Bss transition using 802.1X */ ++#define RSN_AKM_FBT_PSK 4 /* Fast Bss transition using Pre-shared Key */ ++#define RSN_AKM_MFP_1X 5 /* SHA256 key derivation, using 802.1X */ ++#define RSN_AKM_MFP_PSK 6 /* SHA256 key derivation, using Pre-shared Key */ ++#define RSN_AKM_TPK 7 /* TPK(TDLS Peer Key) handshake */ ++ ++/* Key related defines */ ++#define DOT11_MAX_DEFAULT_KEYS 4 /* number of default keys */ ++#define DOT11_MAX_KEY_SIZE 32 /* max size of any key */ ++#define DOT11_MAX_IV_SIZE 16 /* max size of any IV */ ++#define DOT11_EXT_IV_FLAG (1<<5) /* flag to indicate IV is > 4 bytes */ ++#define DOT11_WPA_KEY_RSC_LEN 8 /* WPA RSC key len */ ++ ++#define WEP1_KEY_SIZE 5 /* max size of any WEP key */ ++#define WEP1_KEY_HEX_SIZE 10 /* size of WEP key in hex. */ ++#define WEP128_KEY_SIZE 13 /* max size of any WEP key */ ++#define WEP128_KEY_HEX_SIZE 26 /* size of WEP key in hex. */ ++#define TKIP_MIC_SIZE 8 /* size of TKIP MIC */ ++#define TKIP_EOM_SIZE 7 /* max size of TKIP EOM */ ++#define TKIP_EOM_FLAG 0x5a /* TKIP EOM flag byte */ ++#define TKIP_KEY_SIZE 32 /* size of any TKIP key */ ++#define TKIP_MIC_AUTH_TX 16 /* offset to Authenticator MIC TX key */ ++#define TKIP_MIC_AUTH_RX 24 /* offset to Authenticator MIC RX key */ ++#define TKIP_MIC_SUP_RX TKIP_MIC_AUTH_TX /* offset to Supplicant MIC RX key */ ++#define TKIP_MIC_SUP_TX TKIP_MIC_AUTH_RX /* offset to Supplicant MIC TX key */ ++#define AES_KEY_SIZE 16 /* size of AES key */ ++#define AES_MIC_SIZE 8 /* size of AES MIC */ ++#define BIP_KEY_SIZE 16 /* size of BIP key */ ++ ++/* WCN */ ++#define WCN_OUI "\x00\x50\xf2" /* WCN OUI */ ++#define WCN_TYPE 4 /* WCN type */ ++#ifdef BCMWAPI_WPI ++#define SMS4_KEY_LEN 16 ++#define SMS4_WPI_CBC_MAC_LEN 16 ++#endif ++ ++ ++/* 802.11r protocol definitions */ ++ ++/* Mobility Domain IE */ ++BWL_PRE_PACKED_STRUCT struct dot11_mdid_ie { ++ uint8 id; ++ uint8 len; ++ uint16 mdid; /* Mobility Domain Id */ ++ uint8 cap; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_mdid_ie dot11_mdid_ie_t; ++ ++#define FBT_MDID_CAP_OVERDS 0x01 /* Fast Bss transition over the DS support */ ++#define FBT_MDID_CAP_RRP 0x02 /* Resource request protocol support */ ++ ++/* Fast Bss Transition IE */ ++BWL_PRE_PACKED_STRUCT struct dot11_ft_ie { ++ uint8 id; ++ uint8 len; ++ uint16 mic_control; /* Mic Control */ ++ uint8 mic[16]; ++ uint8 anonce[32]; ++ uint8 snonce[32]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_ft_ie dot11_ft_ie_t; ++ ++#define TIE_TYPE_RESERVED 0 ++#define TIE_TYPE_REASSOC_DEADLINE 1 ++#define TIE_TYPE_KEY_LIEFTIME 2 ++#define TIE_TYPE_ASSOC_COMEBACK 3 ++BWL_PRE_PACKED_STRUCT struct dot11_timeout_ie { ++ uint8 id; ++ uint8 len; ++ uint8 type; /* timeout interval type */ ++ uint32 value; /* timeout interval value */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_timeout_ie dot11_timeout_ie_t; ++ ++ ++/* GTK ie */ ++BWL_PRE_PACKED_STRUCT struct dot11_gtk_ie { ++ uint8 id; ++ uint8 len; ++ uint16 key_info; ++ uint8 key_len; ++ uint8 rsc[8]; ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT; ++typedef struct dot11_gtk_ie dot11_gtk_ie_t; ++ ++#define BSSID_INVALID "\x00\x00\x00\x00\x00\x00" ++#define BSSID_BROADCAST "\xFF\xFF\xFF\xFF\xFF\xFF" ++ ++ ++/* ************* WMM Parameter definitions. ************* */ ++#define WMM_OUI "\x00\x50\xF2" /* WNN OUI */ ++#define WMM_OUI_LEN 3 /* WMM OUI length */ ++#define WMM_OUI_TYPE 2 /* WMM OUT type */ ++#define WMM_VERSION 1 ++#define WMM_VERSION_LEN 1 ++ ++/* WMM OUI subtype */ ++#define WMM_OUI_SUBTYPE_PARAMETER 1 ++#define WMM_PARAMETER_IE_LEN 24 ++ ++/* Link Identifier Element */ ++BWL_PRE_PACKED_STRUCT struct link_id_ie { ++ uint8 id; ++ uint8 len; ++ struct ether_addr bssid; ++ struct ether_addr tdls_init_mac; ++ struct ether_addr tdls_resp_mac; ++} BWL_POST_PACKED_STRUCT; ++typedef struct link_id_ie link_id_ie_t; ++#define TDLS_LINK_ID_IE_LEN 18 ++ ++/* Link Wakeup Schedule Element */ ++BWL_PRE_PACKED_STRUCT struct wakeup_sch_ie { ++ uint8 id; ++ uint8 len; ++ uint32 offset; /* in ms between TSF0 and start of 1st Awake Window */ ++ uint32 interval; /* in ms bwtween the start of 2 Awake Windows */ ++ uint32 awake_win_slots; /* in backof slots, duration of Awake Window */ ++ uint32 max_wake_win; /* in ms, max duration of Awake Window */ ++ uint16 idle_cnt; /* number of consecutive Awake Windows */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wakeup_sch_ie wakeup_sch_ie_t; ++#define TDLS_WAKEUP_SCH_IE_LEN 18 ++ ++/* Channel Switch Timing Element */ ++BWL_PRE_PACKED_STRUCT struct channel_switch_timing_ie { ++ uint8 id; ++ uint8 len; ++ uint16 switch_time; /* in ms, time to switch channels */ ++ uint16 switch_timeout; /* in ms */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct channel_switch_timing_ie channel_switch_timing_ie_t; ++#define TDLS_CHANNEL_SWITCH_TIMING_IE_LEN 4 ++ ++/* PTI Control Element */ ++BWL_PRE_PACKED_STRUCT struct pti_control_ie { ++ uint8 id; ++ uint8 len; ++ uint8 tid; ++ uint16 seq_control; ++} BWL_POST_PACKED_STRUCT; ++typedef struct pti_control_ie pti_control_ie_t; ++#define TDLS_PTI_CONTROL_IE_LEN 3 ++ ++/* PU Buffer Status Element */ ++BWL_PRE_PACKED_STRUCT struct pu_buffer_status_ie { ++ uint8 id; ++ uint8 len; ++ uint8 status; ++} BWL_POST_PACKED_STRUCT; ++typedef struct pu_buffer_status_ie pu_buffer_status_ie_t; ++#define TDLS_PU_BUFFER_STATUS_IE_LEN 1 ++#define TDLS_PU_BUFFER_STATUS_AC_BK 1 ++#define TDLS_PU_BUFFER_STATUS_AC_BE 2 ++#define TDLS_PU_BUFFER_STATUS_AC_VI 4 ++#define TDLS_PU_BUFFER_STATUS_AC_VO 8 ++ ++#ifdef BCMWAPI_WAI ++#define WAPI_IE_MIN_LEN 20 /* WAPI IE min length */ ++#define WAPI_VERSION 1 /* WAPI version */ ++#define WAPI_VERSION_LEN 2 /* WAPI version length */ ++#define WAPI_OUI "\x00\x14\x72" /* WAPI OUI */ ++#define WAPI_OUI_LEN DOT11_OUI_LEN /* WAPI OUI length */ ++#endif /* BCMWAPI_WAI */ ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _802_11_H_ */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/proto/802.1d.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/proto/802.1d.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/proto/802.1d.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/proto/802.1d.h 2014-02-15 00:43:44.793014092 +0100 +@@ -0,0 +1,50 @@ ++/* ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * Fundamental types and constants relating to 802.1D ++ * ++ * $Id: 802.1d.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _802_1_D_ ++#define _802_1_D_ ++ ++/* 802.1D priority defines */ ++#define PRIO_8021D_NONE 2 /* None = - */ ++#define PRIO_8021D_BK 1 /* BK - Background */ ++#define PRIO_8021D_BE 0 /* BE - Best-effort */ ++#define PRIO_8021D_EE 3 /* EE - Excellent-effort */ ++#define PRIO_8021D_CL 4 /* CL - Controlled Load */ ++#define PRIO_8021D_VI 5 /* Vi - Video */ ++#define PRIO_8021D_VO 6 /* Vo - Voice */ ++#define PRIO_8021D_NC 7 /* NC - Network Control */ ++#define MAXPRIO 7 /* 0-7 */ ++#define NUMPRIO (MAXPRIO + 1) ++ ++#define ALLPRIO -1 /* All prioirty */ ++ ++/* Converts prio to precedence since the numerical value of ++ * PRIO_8021D_BE and PRIO_8021D_NONE are swapped. ++ */ ++#define PRIO2PREC(prio) \ ++ (((prio) == PRIO_8021D_NONE || (prio) == PRIO_8021D_BE) ? ((prio^2)) : (prio)) ++ ++#endif /* _802_1_D__ */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/proto/bcmeth.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/proto/bcmeth.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/proto/bcmeth.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/proto/bcmeth.h 2014-02-15 00:43:44.793014092 +0100 +@@ -0,0 +1,112 @@ ++/* ++ * Broadcom Ethernettype protocol definitions ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: bcmeth.h 294352 2011-11-06 19:23:00Z $ ++ */ ++ ++/* ++ * Broadcom Ethernet protocol defines ++ */ ++ ++#ifndef _BCMETH_H_ ++#define _BCMETH_H_ ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++/* ETHER_TYPE_BRCM is defined in ethernet.h */ ++ ++/* ++ * Following the 2byte BRCM ether_type is a 16bit BRCM subtype field ++ * in one of two formats: (only subtypes 32768-65535 are in use now) ++ * ++ * subtypes 0-32767: ++ * 8 bit subtype (0-127) ++ * 8 bit length in bytes (0-255) ++ * ++ * subtypes 32768-65535: ++ * 16 bit big-endian subtype ++ * 16 bit big-endian length in bytes (0-65535) ++ * ++ * length is the number of additional bytes beyond the 4 or 6 byte header ++ * ++ * Reserved values: ++ * 0 reserved ++ * 5-15 reserved for iLine protocol assignments ++ * 17-126 reserved, assignable ++ * 127 reserved ++ * 32768 reserved ++ * 32769-65534 reserved, assignable ++ * 65535 reserved ++ */ ++ ++/* ++ * While adding the subtypes and their specific processing code make sure ++ * bcmeth_bcm_hdr_t is the first data structure in the user specific data structure definition ++ */ ++ ++#define BCMILCP_SUBTYPE_RATE 1 ++#define BCMILCP_SUBTYPE_LINK 2 ++#define BCMILCP_SUBTYPE_CSA 3 ++#define BCMILCP_SUBTYPE_LARQ 4 ++#define BCMILCP_SUBTYPE_VENDOR 5 ++#define BCMILCP_SUBTYPE_FLH 17 ++ ++#define BCMILCP_SUBTYPE_VENDOR_LONG 32769 ++#define BCMILCP_SUBTYPE_CERT 32770 ++#define BCMILCP_SUBTYPE_SES 32771 ++ ++ ++#define BCMILCP_BCM_SUBTYPE_RESERVED 0 ++#define BCMILCP_BCM_SUBTYPE_EVENT 1 ++#define BCMILCP_BCM_SUBTYPE_SES 2 ++/* ++ * The EAPOL type is not used anymore. Instead EAPOL messages are now embedded ++ * within BCMILCP_BCM_SUBTYPE_EVENT type messages ++ */ ++/* #define BCMILCP_BCM_SUBTYPE_EAPOL 3 */ ++#define BCMILCP_BCM_SUBTYPE_DPT 4 ++ ++#define BCMILCP_BCM_SUBTYPEHDR_MINLENGTH 8 ++#define BCMILCP_BCM_SUBTYPEHDR_VERSION 0 ++ ++/* These fields are stored in network order */ ++typedef BWL_PRE_PACKED_STRUCT struct bcmeth_hdr ++{ ++ uint16 subtype; /* Vendor specific..32769 */ ++ uint16 length; ++ uint8 version; /* Version is 0 */ ++ uint8 oui[3]; /* Broadcom OUI */ ++ /* user specific Data */ ++ uint16 usr_subtype; ++} BWL_POST_PACKED_STRUCT bcmeth_hdr_t; ++ ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _BCMETH_H_ */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/proto/bcmevent.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/proto/bcmevent.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/proto/bcmevent.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/proto/bcmevent.h 2014-02-15 00:43:44.793014092 +0100 +@@ -0,0 +1,368 @@ ++/* ++ * Broadcom Event protocol definitions ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * Dependencies: proto/bcmeth.h ++ * ++ * $Id: bcmevent.h 374275 2012-12-12 11:44:18Z $ ++ * ++ */ ++ ++/* ++ * Broadcom Ethernet Events protocol defines ++ * ++ */ ++ ++#ifndef _BCMEVENT_H_ ++#define _BCMEVENT_H_ ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++#define BCM_EVENT_MSG_VERSION 2 /* wl_event_msg_t struct version */ ++#define BCM_MSG_IFNAME_MAX 16 /* max length of interface name */ ++ ++/* flags */ ++#define WLC_EVENT_MSG_LINK 0x01 /* link is up */ ++#define WLC_EVENT_MSG_FLUSHTXQ 0x02 /* flush tx queue on MIC error */ ++#define WLC_EVENT_MSG_GROUP 0x04 /* group MIC error */ ++#define WLC_EVENT_MSG_UNKBSS 0x08 /* unknown source bsscfg */ ++#define WLC_EVENT_MSG_UNKIF 0x10 /* unknown source OS i/f */ ++ ++/* these fields are stored in network order */ ++ ++/* version 1 */ ++typedef BWL_PRE_PACKED_STRUCT struct ++{ ++ uint16 version; ++ uint16 flags; /* see flags below */ ++ uint32 event_type; /* Message (see below) */ ++ uint32 status; /* Status code (see below) */ ++ uint32 reason; /* Reason code (if applicable) */ ++ uint32 auth_type; /* WLC_E_AUTH */ ++ uint32 datalen; /* data buf */ ++ struct ether_addr addr; /* Station address (if applicable) */ ++ char ifname[BCM_MSG_IFNAME_MAX]; /* name of the packet incoming interface */ ++} BWL_POST_PACKED_STRUCT wl_event_msg_v1_t; ++ ++/* the current version */ ++typedef BWL_PRE_PACKED_STRUCT struct ++{ ++ uint16 version; ++ uint16 flags; /* see flags below */ ++ uint32 event_type; /* Message (see below) */ ++ uint32 status; /* Status code (see below) */ ++ uint32 reason; /* Reason code (if applicable) */ ++ uint32 auth_type; /* WLC_E_AUTH */ ++ uint32 datalen; /* data buf */ ++ struct ether_addr addr; /* Station address (if applicable) */ ++ char ifname[BCM_MSG_IFNAME_MAX]; /* name of the packet incoming interface */ ++ uint8 ifidx; /* destination OS i/f index */ ++ uint8 bsscfgidx; /* source bsscfg index */ ++} BWL_POST_PACKED_STRUCT wl_event_msg_t; ++ ++/* used by driver msgs */ ++typedef BWL_PRE_PACKED_STRUCT struct bcm_event { ++ struct ether_header eth; ++ bcmeth_hdr_t bcm_hdr; ++ wl_event_msg_t event; ++ /* data portion follows */ ++} BWL_POST_PACKED_STRUCT bcm_event_t; ++ ++#define BCM_MSG_LEN (sizeof(bcm_event_t) - sizeof(bcmeth_hdr_t) - sizeof(struct ether_header)) ++ ++/* Event messages */ ++#define WLC_E_SET_SSID 0 /* indicates status of set SSID */ ++#define WLC_E_JOIN 1 /* differentiates join IBSS from found (WLC_E_START) IBSS */ ++#define WLC_E_START 2 /* STA founded an IBSS or AP started a BSS */ ++#define WLC_E_AUTH 3 /* 802.11 AUTH request */ ++#define WLC_E_AUTH_IND 4 /* 802.11 AUTH indication */ ++#define WLC_E_DEAUTH 5 /* 802.11 DEAUTH request */ ++#define WLC_E_DEAUTH_IND 6 /* 802.11 DEAUTH indication */ ++#define WLC_E_ASSOC 7 /* 802.11 ASSOC request */ ++#define WLC_E_ASSOC_IND 8 /* 802.11 ASSOC indication */ ++#define WLC_E_REASSOC 9 /* 802.11 REASSOC request */ ++#define WLC_E_REASSOC_IND 10 /* 802.11 REASSOC indication */ ++#define WLC_E_DISASSOC 11 /* 802.11 DISASSOC request */ ++#define WLC_E_DISASSOC_IND 12 /* 802.11 DISASSOC indication */ ++#define WLC_E_QUIET_START 13 /* 802.11h Quiet period started */ ++#define WLC_E_QUIET_END 14 /* 802.11h Quiet period ended */ ++#define WLC_E_BEACON_RX 15 /* BEACONS received/lost indication */ ++#define WLC_E_LINK 16 /* generic link indication */ ++#define WLC_E_MIC_ERROR 17 /* TKIP MIC error occurred */ ++#define WLC_E_NDIS_LINK 18 /* NDIS style link indication */ ++#define WLC_E_ROAM 19 /* roam attempt occurred: indicate status & reason */ ++#define WLC_E_TXFAIL 20 /* change in dot11FailedCount (txfail) */ ++#define WLC_E_PMKID_CACHE 21 /* WPA2 pmkid cache indication */ ++#define WLC_E_RETROGRADE_TSF 22 /* current AP's TSF value went backward */ ++#define WLC_E_PRUNE 23 /* AP was pruned from join list for reason */ ++#define WLC_E_AUTOAUTH 24 /* report AutoAuth table entry match for join attempt */ ++#define WLC_E_EAPOL_MSG 25 /* Event encapsulating an EAPOL message */ ++#define WLC_E_SCAN_COMPLETE 26 /* Scan results are ready or scan was aborted */ ++#define WLC_E_ADDTS_IND 27 /* indicate to host addts fail/success */ ++#define WLC_E_DELTS_IND 28 /* indicate to host delts fail/success */ ++#define WLC_E_BCNSENT_IND 29 /* indicate to host of beacon transmit */ ++#define WLC_E_BCNRX_MSG 30 /* Send the received beacon up to the host */ ++#define WLC_E_BCNLOST_MSG 31 /* indicate to host loss of beacon */ ++#define WLC_E_ROAM_PREP 32 /* before attempting to roam */ ++#define WLC_E_PFN_NET_FOUND 33 /* PFN network found event */ ++#define WLC_E_PFN_NET_LOST 34 /* PFN network lost event */ ++#define WLC_E_RESET_COMPLETE 35 ++#define WLC_E_JOIN_START 36 ++#define WLC_E_ROAM_START 37 ++#define WLC_E_ASSOC_START 38 ++#define WLC_E_IBSS_ASSOC 39 ++#define WLC_E_RADIO 40 ++#define WLC_E_PSM_WATCHDOG 41 /* PSM microcode watchdog fired */ ++#define WLC_E_PROBREQ_MSG 44 /* probe request received */ ++#define WLC_E_SCAN_CONFIRM_IND 45 ++#define WLC_E_PSK_SUP 46 /* WPA Handshake fail */ ++#define WLC_E_COUNTRY_CODE_CHANGED 47 ++#define WLC_E_EXCEEDED_MEDIUM_TIME 48 /* WMMAC excedded medium time */ ++#define WLC_E_ICV_ERROR 49 /* WEP ICV error occurred */ ++#define WLC_E_UNICAST_DECODE_ERROR 50 /* Unsupported unicast encrypted frame */ ++#define WLC_E_MULTICAST_DECODE_ERROR 51 /* Unsupported multicast encrypted frame */ ++#define WLC_E_TRACE 52 ++#ifdef WLBTAMP ++#define WLC_E_BTA_HCI_EVENT 53 /* BT-AMP HCI event */ ++#endif ++#define WLC_E_IF 54 /* I/F change (for dongle host notification) */ ++#define WLC_E_P2P_DISC_LISTEN_COMPLETE 55 /* listen state expires */ ++#define WLC_E_RSSI 56 /* indicate RSSI change based on configured levels */ ++#define WLC_E_PFN_SCAN_COMPLETE 57 /* PFN completed scan of network list */ ++#define WLC_E_EXTLOG_MSG 58 ++#define WLC_E_ACTION_FRAME 59 /* Action frame Rx */ ++#define WLC_E_ACTION_FRAME_COMPLETE 60 /* Action frame Tx complete */ ++#define WLC_E_PRE_ASSOC_IND 61 /* assoc request received */ ++#define WLC_E_PRE_REASSOC_IND 62 /* re-assoc request received */ ++#define WLC_E_CHANNEL_ADOPTED 63 ++#define WLC_E_AP_STARTED 64 /* AP started */ ++#define WLC_E_DFS_AP_STOP 65 /* AP stopped due to DFS */ ++#define WLC_E_DFS_AP_RESUME 66 /* AP resumed due to DFS */ ++#define WLC_E_WAI_STA_EVENT 67 /* WAI stations event */ ++#define WLC_E_WAI_MSG 68 /* event encapsulating an WAI message */ ++#define WLC_E_ESCAN_RESULT 69 /* escan result event */ ++#define WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE 70 /* action frame off channel complete */ ++#define WLC_E_PROBRESP_MSG 71 /* probe response received */ ++#define WLC_E_P2P_PROBREQ_MSG 72 /* P2P Probe request received */ ++#define WLC_E_DCS_REQUEST 73 ++ ++#define WLC_E_FIFO_CREDIT_MAP 74 /* credits for D11 FIFOs. [AC0,AC1,AC2,AC3,BC_MC,ATIM] */ ++ ++#define WLC_E_ACTION_FRAME_RX 75 /* Received action frame event WITH ++ * wl_event_rx_frame_data_t header ++ */ ++#define WLC_E_WAKE_EVENT 76 /* Wake Event timer fired, used for wake WLAN test mode */ ++#define WLC_E_RM_COMPLETE 77 /* Radio measurement complete */ ++#define WLC_E_HTSFSYNC 78 /* Synchronize TSF with the host */ ++#define WLC_E_OVERLAY_REQ 79 /* request an overlay IOCTL/iovar from the host */ ++#define WLC_E_CSA_COMPLETE_IND 80 /* 802.11 CHANNEL SWITCH ACTION completed */ ++#define WLC_E_EXCESS_PM_WAKE_EVENT 81 /* excess PM Wake Event to inform host */ ++#define WLC_E_PFN_SCAN_NONE 82 /* no PFN networks around */ ++#define WLC_E_PFN_SCAN_ALLGONE 83 /* last found PFN network gets lost */ ++#define WLC_E_GTK_PLUMBED 84 ++#define WLC_E_ASSOC_IND_NDIS 85 /* 802.11 ASSOC indication for NDIS only */ ++#define WLC_E_REASSOC_IND_NDIS 86 /* 802.11 REASSOC indication for NDIS only */ ++#define WLC_E_ASSOC_REQ_IE 87 ++#define WLC_E_ASSOC_RESP_IE 88 ++#define WLC_E_ASSOC_RECREATED 89 /* association recreated on resume */ ++#define WLC_E_ACTION_FRAME_RX_NDIS 90 /* rx action frame event for NDIS only */ ++#define WLC_E_AUTH_REQ 91 /* authentication request received */ ++#define WLC_E_TDLS_PEER_EVENT 92 /* discovered peer, connected or disconnected peer */ ++#define WLC_E_SPEEDY_RECREATE_FAIL 93 /* fast assoc recreation failed */ ++#define WLC_E_SERVICE_FOUND 102 /* desired service found */ ++#define WLC_E_GAS_FRAGMENT_RX 103 /* GAS fragment received */ ++#define WLC_E_GAS_COMPLETE 104 /* GAS sessions all complete */ ++#define WLC_E_P2PO_ADD_DEVICE 105 /* New device found by p2p offload */ ++#define WLC_E_P2PO_DEL_DEVICE 106 /* device has been removed by p2p offload */ ++#define WLC_E_LAST 107 /* highest val + 1 for range checking */ ++ ++ ++/* Table of event name strings for UIs and debugging dumps */ ++typedef struct { ++ uint event; ++ const char *name; ++} bcmevent_name_t; ++ ++extern const bcmevent_name_t bcmevent_names[]; ++extern const int bcmevent_names_size; ++ ++/* Event status codes */ ++#define WLC_E_STATUS_SUCCESS 0 /* operation was successful */ ++#define WLC_E_STATUS_FAIL 1 /* operation failed */ ++#define WLC_E_STATUS_TIMEOUT 2 /* operation timed out */ ++#define WLC_E_STATUS_NO_NETWORKS 3 /* failed due to no matching network found */ ++#define WLC_E_STATUS_ABORT 4 /* operation was aborted */ ++#define WLC_E_STATUS_NO_ACK 5 /* protocol failure: packet not ack'd */ ++#define WLC_E_STATUS_UNSOLICITED 6 /* AUTH or ASSOC packet was unsolicited */ ++#define WLC_E_STATUS_ATTEMPT 7 /* attempt to assoc to an auto auth configuration */ ++#define WLC_E_STATUS_PARTIAL 8 /* scan results are incomplete */ ++#define WLC_E_STATUS_NEWSCAN 9 /* scan aborted by another scan */ ++#define WLC_E_STATUS_NEWASSOC 10 /* scan aborted due to assoc in progress */ ++#define WLC_E_STATUS_11HQUIET 11 /* 802.11h quiet period started */ ++#define WLC_E_STATUS_SUPPRESS 12 /* user disabled scanning (WLC_SET_SCANSUPPRESS) */ ++#define WLC_E_STATUS_NOCHANS 13 /* no allowable channels to scan */ ++#define WLC_E_STATUS_CS_ABORT 15 /* abort channel select */ ++#define WLC_E_STATUS_ERROR 16 /* request failed due to error */ ++ ++/* roam reason codes */ ++#define WLC_E_REASON_INITIAL_ASSOC 0 /* initial assoc */ ++#define WLC_E_REASON_LOW_RSSI 1 /* roamed due to low RSSI */ ++#define WLC_E_REASON_DEAUTH 2 /* roamed due to DEAUTH indication */ ++#define WLC_E_REASON_DISASSOC 3 /* roamed due to DISASSOC indication */ ++#define WLC_E_REASON_BCNS_LOST 4 /* roamed due to lost beacons */ ++#define WLC_E_REASON_MINTXRATE 9 /* roamed because at mintxrate for too long */ ++#define WLC_E_REASON_TXFAIL 10 /* We can hear AP, but AP can't hear us */ ++ ++/* Roam codes used primarily by CCX */ ++#define WLC_E_REASON_FAST_ROAM_FAILED 5 /* roamed due to fast roam failure */ ++#define WLC_E_REASON_DIRECTED_ROAM 6 /* roamed due to request by AP */ ++#define WLC_E_REASON_TSPEC_REJECTED 7 /* roamed due to TSPEC rejection */ ++#define WLC_E_REASON_BETTER_AP 8 /* roamed due to finding better AP */ ++ ++ ++#define WLC_E_REASON_REQUESTED_ROAM 11 /* roamed due to BSS Mgmt Transition request by AP */ ++ ++/* prune reason codes */ ++#define WLC_E_PRUNE_ENCR_MISMATCH 1 /* encryption mismatch */ ++#define WLC_E_PRUNE_BCAST_BSSID 2 /* AP uses a broadcast BSSID */ ++#define WLC_E_PRUNE_MAC_DENY 3 /* STA's MAC addr is in AP's MAC deny list */ ++#define WLC_E_PRUNE_MAC_NA 4 /* STA's MAC addr is not in AP's MAC allow list */ ++#define WLC_E_PRUNE_REG_PASSV 5 /* AP not allowed due to regulatory restriction */ ++#define WLC_E_PRUNE_SPCT_MGMT 6 /* AP does not support STA locale spectrum mgmt */ ++#define WLC_E_PRUNE_RADAR 7 /* AP is on a radar channel of STA locale */ ++#define WLC_E_RSN_MISMATCH 8 /* STA does not support AP's RSN */ ++#define WLC_E_PRUNE_NO_COMMON_RATES 9 /* No rates in common with AP */ ++#define WLC_E_PRUNE_BASIC_RATES 10 /* STA does not support all basic rates of BSS */ ++#define WLC_E_PRUNE_CIPHER_NA 12 /* BSS's cipher not supported */ ++#define WLC_E_PRUNE_KNOWN_STA 13 /* AP is already known to us as a STA */ ++#define WLC_E_PRUNE_WDS_PEER 15 /* AP is already known to us as a WDS peer */ ++#define WLC_E_PRUNE_QBSS_LOAD 16 /* QBSS LOAD - AAC is too low */ ++#define WLC_E_PRUNE_HOME_AP 17 /* prune home AP */ ++ ++/* WPA failure reason codes carried in the WLC_E_PSK_SUP event */ ++#define WLC_E_SUP_OTHER 0 /* Other reason */ ++#define WLC_E_SUP_DECRYPT_KEY_DATA 1 /* Decryption of key data failed */ ++#define WLC_E_SUP_BAD_UCAST_WEP128 2 /* Illegal use of ucast WEP128 */ ++#define WLC_E_SUP_BAD_UCAST_WEP40 3 /* Illegal use of ucast WEP40 */ ++#define WLC_E_SUP_UNSUP_KEY_LEN 4 /* Unsupported key length */ ++#define WLC_E_SUP_PW_KEY_CIPHER 5 /* Unicast cipher mismatch in pairwise key */ ++#define WLC_E_SUP_MSG3_TOO_MANY_IE 6 /* WPA IE contains > 1 RSN IE in key msg 3 */ ++#define WLC_E_SUP_MSG3_IE_MISMATCH 7 /* WPA IE mismatch in key message 3 */ ++#define WLC_E_SUP_NO_INSTALL_FLAG 8 /* INSTALL flag unset in 4-way msg */ ++#define WLC_E_SUP_MSG3_NO_GTK 9 /* encapsulated GTK missing from msg 3 */ ++#define WLC_E_SUP_GRP_KEY_CIPHER 10 /* Multicast cipher mismatch in group key */ ++#define WLC_E_SUP_GRP_MSG1_NO_GTK 11 /* encapsulated GTK missing from group msg 1 */ ++#define WLC_E_SUP_GTK_DECRYPT_FAIL 12 /* GTK decrypt failure */ ++#define WLC_E_SUP_SEND_FAIL 13 /* message send failure */ ++#define WLC_E_SUP_DEAUTH 14 /* received FC_DEAUTH */ ++#define WLC_E_SUP_WPA_PSK_TMO 15 /* WPA PSK 4-way handshake timeout */ ++ ++/* Event data for events that include frames received over the air */ ++/* WLC_E_PROBRESP_MSG ++ * WLC_E_P2P_PROBREQ_MSG ++ * WLC_E_ACTION_FRAME_RX ++ */ ++typedef BWL_PRE_PACKED_STRUCT struct wl_event_rx_frame_data { ++ uint16 version; ++ uint16 channel; /* Matches chanspec_t format from bcmwifi_channels.h */ ++ int32 rssi; ++ uint32 mactime; ++ uint32 rate; ++} BWL_POST_PACKED_STRUCT wl_event_rx_frame_data_t; ++ ++#define BCM_RX_FRAME_DATA_VERSION 1 ++ ++/* WLC_E_IF event data */ ++typedef struct wl_event_data_if { ++ uint8 ifidx; /* RTE virtual device index (for dongle) */ ++ uint8 opcode; /* see I/F opcode */ ++ uint8 reserved; ++ uint8 bssidx; /* bsscfg index */ ++ uint8 role; /* see I/F role */ ++} wl_event_data_if_t; ++ ++/* opcode in WLC_E_IF event */ ++#define WLC_E_IF_ADD 1 /* bsscfg add */ ++#define WLC_E_IF_DEL 2 /* bsscfg delete */ ++#define WLC_E_IF_CHANGE 3 /* bsscfg role change */ ++ ++/* I/F role code in WLC_E_IF event */ ++#define WLC_E_IF_ROLE_STA 0 /* Infra STA */ ++#define WLC_E_IF_ROLE_AP 1 /* Access Point */ ++#define WLC_E_IF_ROLE_WDS 2 /* WDS link */ ++#define WLC_E_IF_ROLE_P2P_GO 3 /* P2P Group Owner */ ++#define WLC_E_IF_ROLE_P2P_CLIENT 4 /* P2P Client */ ++#ifdef WLBTAMP ++#define WLC_E_IF_ROLE_BTA_CREATOR 5 /* BT-AMP Creator */ ++#define WLC_E_IF_ROLE_BTA_ACCEPTOR 6 /* BT-AMP Acceptor */ ++#endif ++ ++/* Reason codes for LINK */ ++#define WLC_E_LINK_BCN_LOSS 1 /* Link down because of beacon loss */ ++#define WLC_E_LINK_DISASSOC 2 /* Link down because of disassoc */ ++#define WLC_E_LINK_ASSOC_REC 3 /* Link down because assoc recreate failed */ ++#define WLC_E_LINK_BSSCFG_DIS 4 /* Link down due to bsscfg down */ ++ ++/* reason codes for WLC_E_OVERLAY_REQ event */ ++#define WLC_E_OVL_DOWNLOAD 0 /* overlay download request */ ++#define WLC_E_OVL_UPDATE_IND 1 /* device indication of host overlay update */ ++ ++/* reason codes for WLC_E_TDLS_PEER_EVENT event */ ++#define WLC_E_TDLS_PEER_DISCOVERED 0 /* peer is ready to establish TDLS */ ++#define WLC_E_TDLS_PEER_CONNECTED 1 ++#define WLC_E_TDLS_PEER_DISCONNECTED 2 ++ ++/* GAS event data */ ++typedef BWL_PRE_PACKED_STRUCT struct wl_event_gas { ++ uint16 channel; /* channel of GAS protocol */ ++ uint8 dialog_token; /* GAS dialog token */ ++ uint8 fragment_id; /* fragment id */ ++ uint16 status_code; /* status code on GAS completion */ ++ uint16 data_len; /* length of data to follow */ ++ uint8 data[1]; /* variable length specified by data_len */ ++} BWL_POST_PACKED_STRUCT wl_event_gas_t; ++ ++/* service discovery TLV */ ++typedef BWL_PRE_PACKED_STRUCT struct wl_sd_tlv { ++ uint16 length; /* length of response_data */ ++ uint8 protocol; /* service protocol type */ ++ uint8 transaction_id; /* service transaction id */ ++ uint8 status_code; /* status code */ ++ uint8 data[1]; /* response data */ ++} BWL_POST_PACKED_STRUCT wl_sd_tlv_t; ++ ++/* service discovery event data */ ++typedef BWL_PRE_PACKED_STRUCT struct wl_event_sd { ++ uint16 channel; /* channel */ ++ uint8 count; /* number of tlvs */ ++ wl_sd_tlv_t tlv[1]; /* service discovery TLV */ ++} BWL_POST_PACKED_STRUCT wl_event_sd_t; ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _BCMEVENT_H_ */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/proto/bcmip.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/proto/bcmip.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/proto/bcmip.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/proto/bcmip.h 2014-02-15 00:43:44.793014092 +0100 +@@ -0,0 +1,210 @@ ++/* ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * Fundamental constants relating to IP Protocol ++ * ++ * $Id: bcmip.h 290206 2011-10-17 19:13:51Z $ ++ */ ++ ++#ifndef _bcmip_h_ ++#define _bcmip_h_ ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++ ++/* IPV4 and IPV6 common */ ++#define IP_VER_OFFSET 0x0 /* offset to version field */ ++#define IP_VER_MASK 0xf0 /* version mask */ ++#define IP_VER_SHIFT 4 /* version shift */ ++#define IP_VER_4 4 /* version number for IPV4 */ ++#define IP_VER_6 6 /* version number for IPV6 */ ++ ++#define IP_VER(ip_body) \ ++ ((((uint8 *)(ip_body))[IP_VER_OFFSET] & IP_VER_MASK) >> IP_VER_SHIFT) ++ ++#define IP_PROT_ICMP 0x1 /* ICMP protocol */ ++#define IP_PROT_IGMP 0x2 /* IGMP protocol */ ++#define IP_PROT_TCP 0x6 /* TCP protocol */ ++#define IP_PROT_UDP 0x11 /* UDP protocol type */ ++#define IP_PROT_ICMP6 0x3a /* ICMPv6 protocol type */ ++ ++/* IPV4 field offsets */ ++#define IPV4_VER_HL_OFFSET 0 /* version and ihl byte offset */ ++#define IPV4_TOS_OFFSET 1 /* type of service offset */ ++#define IPV4_PKTLEN_OFFSET 2 /* packet length offset */ ++#define IPV4_PKTFLAG_OFFSET 6 /* more-frag,dont-frag flag offset */ ++#define IPV4_PROT_OFFSET 9 /* protocol type offset */ ++#define IPV4_CHKSUM_OFFSET 10 /* IP header checksum offset */ ++#define IPV4_SRC_IP_OFFSET 12 /* src IP addr offset */ ++#define IPV4_DEST_IP_OFFSET 16 /* dest IP addr offset */ ++#define IPV4_OPTIONS_OFFSET 20 /* IP options offset */ ++ ++/* IPV4 field decodes */ ++#define IPV4_VER_MASK 0xf0 /* IPV4 version mask */ ++#define IPV4_VER_SHIFT 4 /* IPV4 version shift */ ++ ++#define IPV4_HLEN_MASK 0x0f /* IPV4 header length mask */ ++#define IPV4_HLEN(ipv4_body) (4 * (((uint8 *)(ipv4_body))[IPV4_VER_HL_OFFSET] & IPV4_HLEN_MASK)) ++ ++#define IPV4_ADDR_LEN 4 /* IPV4 address length */ ++ ++#define IPV4_ADDR_NULL(a) ((((uint8 *)(a))[0] | ((uint8 *)(a))[1] | \ ++ ((uint8 *)(a))[2] | ((uint8 *)(a))[3]) == 0) ++ ++#define IPV4_ADDR_BCAST(a) ((((uint8 *)(a))[0] & ((uint8 *)(a))[1] & \ ++ ((uint8 *)(a))[2] & ((uint8 *)(a))[3]) == 0xff) ++ ++#define IPV4_TOS_DSCP_MASK 0xfc /* DiffServ codepoint mask */ ++#define IPV4_TOS_DSCP_SHIFT 2 /* DiffServ codepoint shift */ ++ ++#define IPV4_TOS(ipv4_body) (((uint8 *)(ipv4_body))[IPV4_TOS_OFFSET]) ++ ++#define IPV4_TOS_PREC_MASK 0xe0 /* Historical precedence mask */ ++#define IPV4_TOS_PREC_SHIFT 5 /* Historical precedence shift */ ++ ++#define IPV4_TOS_LOWDELAY 0x10 /* Lowest delay requested */ ++#define IPV4_TOS_THROUGHPUT 0x8 /* Best throughput requested */ ++#define IPV4_TOS_RELIABILITY 0x4 /* Most reliable delivery requested */ ++ ++#define IPV4_PROT(ipv4_body) (((uint8 *)(ipv4_body))[IPV4_PROT_OFFSET]) ++ ++#define IPV4_FRAG_RESV 0x8000 /* Reserved */ ++#define IPV4_FRAG_DONT 0x4000 /* Don't fragment */ ++#define IPV4_FRAG_MORE 0x2000 /* More fragments */ ++#define IPV4_FRAG_OFFSET_MASK 0x1fff /* Fragment offset */ ++ ++#define IPV4_ADDR_STR_LEN 16 /* Max IP address length in string format */ ++ ++/* IPV4 packet formats */ ++BWL_PRE_PACKED_STRUCT struct ipv4_addr { ++ uint8 addr[IPV4_ADDR_LEN]; ++} BWL_POST_PACKED_STRUCT; ++ ++BWL_PRE_PACKED_STRUCT struct ipv4_hdr { ++ uint8 version_ihl; /* Version and Internet Header Length */ ++ uint8 tos; /* Type Of Service */ ++ uint16 tot_len; /* Number of bytes in packet (max 65535) */ ++ uint16 id; ++ uint16 frag; /* 3 flag bits and fragment offset */ ++ uint8 ttl; /* Time To Live */ ++ uint8 prot; /* Protocol */ ++ uint16 hdr_chksum; /* IP header checksum */ ++ uint8 src_ip[IPV4_ADDR_LEN]; /* Source IP Address */ ++ uint8 dst_ip[IPV4_ADDR_LEN]; /* Destination IP Address */ ++} BWL_POST_PACKED_STRUCT; ++ ++/* IPV6 field offsets */ ++#define IPV6_PAYLOAD_LEN_OFFSET 4 /* payload length offset */ ++#define IPV6_NEXT_HDR_OFFSET 6 /* next header/protocol offset */ ++#define IPV6_HOP_LIMIT_OFFSET 7 /* hop limit offset */ ++#define IPV6_SRC_IP_OFFSET 8 /* src IP addr offset */ ++#define IPV6_DEST_IP_OFFSET 24 /* dst IP addr offset */ ++ ++/* IPV6 field decodes */ ++#define IPV6_TRAFFIC_CLASS(ipv6_body) \ ++ (((((uint8 *)(ipv6_body))[0] & 0x0f) << 4) | \ ++ ((((uint8 *)(ipv6_body))[1] & 0xf0) >> 4)) ++ ++#define IPV6_FLOW_LABEL(ipv6_body) \ ++ (((((uint8 *)(ipv6_body))[1] & 0x0f) << 16) | \ ++ (((uint8 *)(ipv6_body))[2] << 8) | \ ++ (((uint8 *)(ipv6_body))[3])) ++ ++#define IPV6_PAYLOAD_LEN(ipv6_body) \ ++ ((((uint8 *)(ipv6_body))[IPV6_PAYLOAD_LEN_OFFSET + 0] << 8) | \ ++ ((uint8 *)(ipv6_body))[IPV6_PAYLOAD_LEN_OFFSET + 1]) ++ ++#define IPV6_NEXT_HDR(ipv6_body) \ ++ (((uint8 *)(ipv6_body))[IPV6_NEXT_HDR_OFFSET]) ++ ++#define IPV6_PROT(ipv6_body) IPV6_NEXT_HDR(ipv6_body) ++ ++#define IPV6_ADDR_LEN 16 /* IPV6 address length */ ++ ++/* IPV4 TOS or IPV6 Traffic Classifier or 0 */ ++#define IP_TOS46(ip_body) \ ++ (IP_VER(ip_body) == IP_VER_4 ? IPV4_TOS(ip_body) : \ ++ IP_VER(ip_body) == IP_VER_6 ? IPV6_TRAFFIC_CLASS(ip_body) : 0) ++ ++/* IPV6 extension headers (options) */ ++#define IPV6_EXTHDR_HOP 0 ++#define IPV6_EXTHDR_ROUTING 43 ++#define IPV6_EXTHDR_FRAGMENT 44 ++#define IPV6_EXTHDR_AUTH 51 ++#define IPV6_EXTHDR_NONE 59 ++#define IPV6_EXTHDR_DEST 60 ++ ++#define IPV6_EXTHDR(prot) (((prot) == IPV6_EXTHDR_HOP) || \ ++ ((prot) == IPV6_EXTHDR_ROUTING) || \ ++ ((prot) == IPV6_EXTHDR_FRAGMENT) || \ ++ ((prot) == IPV6_EXTHDR_AUTH) || \ ++ ((prot) == IPV6_EXTHDR_NONE) || \ ++ ((prot) == IPV6_EXTHDR_DEST)) ++ ++#define IPV6_MIN_HLEN 40 ++ ++#define IPV6_EXTHDR_LEN(eh) ((((struct ipv6_exthdr *)(eh))->hdrlen + 1) << 3) ++ ++BWL_PRE_PACKED_STRUCT struct ipv6_exthdr { ++ uint8 nexthdr; ++ uint8 hdrlen; ++} BWL_POST_PACKED_STRUCT; ++ ++BWL_PRE_PACKED_STRUCT struct ipv6_exthdr_frag { ++ uint8 nexthdr; ++ uint8 rsvd; ++ uint16 frag_off; ++ uint32 ident; ++} BWL_POST_PACKED_STRUCT; ++ ++static INLINE int32 ++ipv6_exthdr_len(uint8 *h, uint8 *proto) ++{ ++ uint16 len = 0, hlen; ++ struct ipv6_exthdr *eh = (struct ipv6_exthdr *)h; ++ ++ while (IPV6_EXTHDR(eh->nexthdr)) { ++ if (eh->nexthdr == IPV6_EXTHDR_NONE) ++ return -1; ++ else if (eh->nexthdr == IPV6_EXTHDR_FRAGMENT) ++ hlen = 8; ++ else if (eh->nexthdr == IPV6_EXTHDR_AUTH) ++ hlen = (eh->hdrlen + 2) << 2; ++ else ++ hlen = IPV6_EXTHDR_LEN(eh); ++ ++ len += hlen; ++ eh = (struct ipv6_exthdr *)(h + len); ++ } ++ ++ *proto = eh->nexthdr; ++ return len; ++} ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _bcmip_h_ */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/proto/bt_amp_hci.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/proto/bt_amp_hci.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/proto/bt_amp_hci.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/proto/bt_amp_hci.h 2014-02-15 00:43:44.793014092 +0100 +@@ -0,0 +1,441 @@ ++/* ++ * BT-AMP (BlueTooth Alternate Mac and Phy) HCI (Host/Controller Interface) ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: bt_amp_hci.h 294267 2011-11-04 23:41:52Z $ ++*/ ++ ++#ifndef _bt_amp_hci_h ++#define _bt_amp_hci_h ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++ ++/* AMP HCI CMD packet format */ ++typedef BWL_PRE_PACKED_STRUCT struct amp_hci_cmd { ++ uint16 opcode; ++ uint8 plen; ++ uint8 parms[1]; ++} BWL_POST_PACKED_STRUCT amp_hci_cmd_t; ++ ++#define HCI_CMD_PREAMBLE_SIZE OFFSETOF(amp_hci_cmd_t, parms) ++#define HCI_CMD_DATA_SIZE 255 ++ ++/* AMP HCI CMD opcode layout */ ++#define HCI_CMD_OPCODE(ogf, ocf) ((((ogf) & 0x3F) << 10) | ((ocf) & 0x03FF)) ++#define HCI_CMD_OGF(opcode) ((uint8)(((opcode) >> 10) & 0x3F)) ++#define HCI_CMD_OCF(opcode) ((opcode) & 0x03FF) ++ ++/* AMP HCI command opcodes */ ++#define HCI_Read_Failed_Contact_Counter HCI_CMD_OPCODE(0x05, 0x0001) ++#define HCI_Reset_Failed_Contact_Counter HCI_CMD_OPCODE(0x05, 0x0002) ++#define HCI_Read_Link_Quality HCI_CMD_OPCODE(0x05, 0x0003) ++#define HCI_Read_Local_AMP_Info HCI_CMD_OPCODE(0x05, 0x0009) ++#define HCI_Read_Local_AMP_ASSOC HCI_CMD_OPCODE(0x05, 0x000A) ++#define HCI_Write_Remote_AMP_ASSOC HCI_CMD_OPCODE(0x05, 0x000B) ++#define HCI_Create_Physical_Link HCI_CMD_OPCODE(0x01, 0x0035) ++#define HCI_Accept_Physical_Link_Request HCI_CMD_OPCODE(0x01, 0x0036) ++#define HCI_Disconnect_Physical_Link HCI_CMD_OPCODE(0x01, 0x0037) ++#define HCI_Create_Logical_Link HCI_CMD_OPCODE(0x01, 0x0038) ++#define HCI_Accept_Logical_Link HCI_CMD_OPCODE(0x01, 0x0039) ++#define HCI_Disconnect_Logical_Link HCI_CMD_OPCODE(0x01, 0x003A) ++#define HCI_Logical_Link_Cancel HCI_CMD_OPCODE(0x01, 0x003B) ++#define HCI_Flow_Spec_Modify HCI_CMD_OPCODE(0x01, 0x003C) ++#define HCI_Write_Flow_Control_Mode HCI_CMD_OPCODE(0x01, 0x0067) ++#define HCI_Read_Best_Effort_Flush_Timeout HCI_CMD_OPCODE(0x01, 0x0069) ++#define HCI_Write_Best_Effort_Flush_Timeout HCI_CMD_OPCODE(0x01, 0x006A) ++#define HCI_Short_Range_Mode HCI_CMD_OPCODE(0x01, 0x006B) ++#define HCI_Reset HCI_CMD_OPCODE(0x03, 0x0003) ++#define HCI_Read_Connection_Accept_Timeout HCI_CMD_OPCODE(0x03, 0x0015) ++#define HCI_Write_Connection_Accept_Timeout HCI_CMD_OPCODE(0x03, 0x0016) ++#define HCI_Read_Link_Supervision_Timeout HCI_CMD_OPCODE(0x03, 0x0036) ++#define HCI_Write_Link_Supervision_Timeout HCI_CMD_OPCODE(0x03, 0x0037) ++#define HCI_Enhanced_Flush HCI_CMD_OPCODE(0x03, 0x005F) ++#define HCI_Read_Logical_Link_Accept_Timeout HCI_CMD_OPCODE(0x03, 0x0061) ++#define HCI_Write_Logical_Link_Accept_Timeout HCI_CMD_OPCODE(0x03, 0x0062) ++#define HCI_Set_Event_Mask_Page_2 HCI_CMD_OPCODE(0x03, 0x0063) ++#define HCI_Read_Location_Data_Command HCI_CMD_OPCODE(0x03, 0x0064) ++#define HCI_Write_Location_Data_Command HCI_CMD_OPCODE(0x03, 0x0065) ++#define HCI_Read_Local_Version_Info HCI_CMD_OPCODE(0x04, 0x0001) ++#define HCI_Read_Local_Supported_Commands HCI_CMD_OPCODE(0x04, 0x0002) ++#define HCI_Read_Buffer_Size HCI_CMD_OPCODE(0x04, 0x0005) ++#define HCI_Read_Data_Block_Size HCI_CMD_OPCODE(0x04, 0x000A) ++ ++/* AMP HCI command parameters */ ++typedef BWL_PRE_PACKED_STRUCT struct read_local_cmd_parms { ++ uint8 plh; ++ uint8 offset[2]; /* length so far */ ++ uint8 max_remote[2]; ++} BWL_POST_PACKED_STRUCT read_local_cmd_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct write_remote_cmd_parms { ++ uint8 plh; ++ uint8 offset[2]; ++ uint8 len[2]; ++ uint8 frag[1]; ++} BWL_POST_PACKED_STRUCT write_remote_cmd_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct phy_link_cmd_parms { ++ uint8 plh; ++ uint8 key_length; ++ uint8 key_type; ++ uint8 key[1]; ++} BWL_POST_PACKED_STRUCT phy_link_cmd_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct dis_phy_link_cmd_parms { ++ uint8 plh; ++ uint8 reason; ++} BWL_POST_PACKED_STRUCT dis_phy_link_cmd_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct log_link_cmd_parms { ++ uint8 plh; ++ uint8 txflow[16]; ++ uint8 rxflow[16]; ++} BWL_POST_PACKED_STRUCT log_link_cmd_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct ext_flow_spec { ++ uint8 id; ++ uint8 service_type; ++ uint8 max_sdu[2]; ++ uint8 sdu_ia_time[4]; ++ uint8 access_latency[4]; ++ uint8 flush_timeout[4]; ++} BWL_POST_PACKED_STRUCT ext_flow_spec_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct log_link_cancel_cmd_parms { ++ uint8 plh; ++ uint8 tx_fs_ID; ++} BWL_POST_PACKED_STRUCT log_link_cancel_cmd_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct flow_spec_mod_cmd_parms { ++ uint8 llh[2]; ++ uint8 txflow[16]; ++ uint8 rxflow[16]; ++} BWL_POST_PACKED_STRUCT flow_spec_mod_cmd_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct plh_pad { ++ uint8 plh; ++ uint8 pad; ++} BWL_POST_PACKED_STRUCT plh_pad_t; ++ ++typedef BWL_PRE_PACKED_STRUCT union hci_handle { ++ uint16 bredr; ++ plh_pad_t amp; ++} BWL_POST_PACKED_STRUCT hci_handle_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct ls_to_cmd_parms { ++ hci_handle_t handle; ++ uint8 timeout[2]; ++} BWL_POST_PACKED_STRUCT ls_to_cmd_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct befto_cmd_parms { ++ uint8 llh[2]; ++ uint8 befto[4]; ++} BWL_POST_PACKED_STRUCT befto_cmd_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct srm_cmd_parms { ++ uint8 plh; ++ uint8 srm; ++} BWL_POST_PACKED_STRUCT srm_cmd_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct ld_cmd_parms { ++ uint8 ld_aware; ++ uint8 ld[2]; ++ uint8 ld_opts; ++ uint8 l_opts; ++} BWL_POST_PACKED_STRUCT ld_cmd_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct eflush_cmd_parms { ++ uint8 llh[2]; ++ uint8 packet_type; ++} BWL_POST_PACKED_STRUCT eflush_cmd_parms_t; ++ ++/* Generic AMP extended flow spec service types */ ++#define EFS_SVCTYPE_NO_TRAFFIC 0 ++#define EFS_SVCTYPE_BEST_EFFORT 1 ++#define EFS_SVCTYPE_GUARANTEED 2 ++ ++/* AMP HCI event packet format */ ++typedef BWL_PRE_PACKED_STRUCT struct amp_hci_event { ++ uint8 ecode; ++ uint8 plen; ++ uint8 parms[1]; ++} BWL_POST_PACKED_STRUCT amp_hci_event_t; ++ ++#define HCI_EVT_PREAMBLE_SIZE OFFSETOF(amp_hci_event_t, parms) ++ ++/* AMP HCI event codes */ ++#define HCI_Command_Complete 0x0E ++#define HCI_Command_Status 0x0F ++#define HCI_Flush_Occurred 0x11 ++#define HCI_Enhanced_Flush_Complete 0x39 ++#define HCI_Physical_Link_Complete 0x40 ++#define HCI_Channel_Select 0x41 ++#define HCI_Disconnect_Physical_Link_Complete 0x42 ++#define HCI_Logical_Link_Complete 0x45 ++#define HCI_Disconnect_Logical_Link_Complete 0x46 ++#define HCI_Flow_Spec_Modify_Complete 0x47 ++#define HCI_Number_of_Completed_Data_Blocks 0x48 ++#define HCI_Short_Range_Mode_Change_Complete 0x4C ++#define HCI_Status_Change_Event 0x4D ++#define HCI_Vendor_Specific 0xFF ++ ++/* AMP HCI event mask bit positions */ ++#define HCI_Physical_Link_Complete_Event_Mask 0x0001 ++#define HCI_Channel_Select_Event_Mask 0x0002 ++#define HCI_Disconnect_Physical_Link_Complete_Event_Mask 0x0004 ++#define HCI_Logical_Link_Complete_Event_Mask 0x0020 ++#define HCI_Disconnect_Logical_Link_Complete_Event_Mask 0x0040 ++#define HCI_Flow_Spec_Modify_Complete_Event_Mask 0x0080 ++#define HCI_Number_of_Completed_Data_Blocks_Event_Mask 0x0100 ++#define HCI_Short_Range_Mode_Change_Complete_Event_Mask 0x1000 ++#define HCI_Status_Change_Event_Mask 0x2000 ++#define HCI_All_Event_Mask 0x31e7 ++/* AMP HCI event parameters */ ++typedef BWL_PRE_PACKED_STRUCT struct cmd_status_parms { ++ uint8 status; ++ uint8 cmdpkts; ++ uint16 opcode; ++} BWL_POST_PACKED_STRUCT cmd_status_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct cmd_complete_parms { ++ uint8 cmdpkts; ++ uint16 opcode; ++ uint8 parms[1]; ++} BWL_POST_PACKED_STRUCT cmd_complete_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct flush_occurred_evt_parms { ++ uint16 handle; ++} BWL_POST_PACKED_STRUCT flush_occurred_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct write_remote_evt_parms { ++ uint8 status; ++ uint8 plh; ++} BWL_POST_PACKED_STRUCT write_remote_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct read_local_evt_parms { ++ uint8 status; ++ uint8 plh; ++ uint16 len; ++ uint8 frag[1]; ++} BWL_POST_PACKED_STRUCT read_local_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct read_local_info_evt_parms { ++ uint8 status; ++ uint8 AMP_status; ++ uint32 bandwidth; ++ uint32 gbandwidth; ++ uint32 latency; ++ uint32 PDU_size; ++ uint8 ctrl_type; ++ uint16 PAL_cap; ++ uint16 AMP_ASSOC_len; ++ uint32 max_flush_timeout; ++ uint32 be_flush_timeout; ++} BWL_POST_PACKED_STRUCT read_local_info_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct log_link_evt_parms { ++ uint8 status; ++ uint16 llh; ++ uint8 plh; ++ uint8 tx_fs_ID; ++} BWL_POST_PACKED_STRUCT log_link_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct disc_log_link_evt_parms { ++ uint8 status; ++ uint16 llh; ++ uint8 reason; ++} BWL_POST_PACKED_STRUCT disc_log_link_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct log_link_cancel_evt_parms { ++ uint8 status; ++ uint8 plh; ++ uint8 tx_fs_ID; ++} BWL_POST_PACKED_STRUCT log_link_cancel_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct flow_spec_mod_evt_parms { ++ uint8 status; ++ uint16 llh; ++} BWL_POST_PACKED_STRUCT flow_spec_mod_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct phy_link_evt_parms { ++ uint8 status; ++ uint8 plh; ++} BWL_POST_PACKED_STRUCT phy_link_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct dis_phy_link_evt_parms { ++ uint8 status; ++ uint8 plh; ++ uint8 reason; ++} BWL_POST_PACKED_STRUCT dis_phy_link_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct read_ls_to_evt_parms { ++ uint8 status; ++ hci_handle_t handle; ++ uint16 timeout; ++} BWL_POST_PACKED_STRUCT read_ls_to_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct read_lla_ca_to_evt_parms { ++ uint8 status; ++ uint16 timeout; ++} BWL_POST_PACKED_STRUCT read_lla_ca_to_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct read_data_block_size_evt_parms { ++ uint8 status; ++ uint16 ACL_pkt_len; ++ uint16 data_block_len; ++ uint16 data_block_num; ++} BWL_POST_PACKED_STRUCT read_data_block_size_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct data_blocks { ++ uint16 handle; ++ uint16 pkts; ++ uint16 blocks; ++} BWL_POST_PACKED_STRUCT data_blocks_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct num_completed_data_blocks_evt_parms { ++ uint16 num_blocks; ++ uint8 num_handles; ++ data_blocks_t completed[1]; ++} BWL_POST_PACKED_STRUCT num_completed_data_blocks_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct befto_evt_parms { ++ uint8 status; ++ uint32 befto; ++} BWL_POST_PACKED_STRUCT befto_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct srm_evt_parms { ++ uint8 status; ++ uint8 plh; ++ uint8 srm; ++} BWL_POST_PACKED_STRUCT srm_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct contact_counter_evt_parms { ++ uint8 status; ++ uint8 llh[2]; ++ uint16 counter; ++} BWL_POST_PACKED_STRUCT contact_counter_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct contact_counter_reset_evt_parms { ++ uint8 status; ++ uint8 llh[2]; ++} BWL_POST_PACKED_STRUCT contact_counter_reset_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct read_linkq_evt_parms { ++ uint8 status; ++ hci_handle_t handle; ++ uint8 link_quality; ++} BWL_POST_PACKED_STRUCT read_linkq_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct ld_evt_parms { ++ uint8 status; ++ uint8 ld_aware; ++ uint8 ld[2]; ++ uint8 ld_opts; ++ uint8 l_opts; ++} BWL_POST_PACKED_STRUCT ld_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct eflush_complete_evt_parms { ++ uint16 handle; ++} BWL_POST_PACKED_STRUCT eflush_complete_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct vendor_specific_evt_parms { ++ uint8 len; ++ uint8 parms[1]; ++} BWL_POST_PACKED_STRUCT vendor_specific_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct local_version_info_evt_parms { ++ uint8 status; ++ uint8 hci_version; ++ uint16 hci_revision; ++ uint8 pal_version; ++ uint16 mfg_name; ++ uint16 pal_subversion; ++} BWL_POST_PACKED_STRUCT local_version_info_evt_parms_t; ++ ++#define MAX_SUPPORTED_CMD_BYTE 64 ++typedef BWL_PRE_PACKED_STRUCT struct local_supported_cmd_evt_parms { ++ uint8 status; ++ uint8 cmd[MAX_SUPPORTED_CMD_BYTE]; ++} BWL_POST_PACKED_STRUCT local_supported_cmd_evt_parms_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct status_change_evt_parms { ++ uint8 status; ++ uint8 amp_status; ++} BWL_POST_PACKED_STRUCT status_change_evt_parms_t; ++ ++/* AMP HCI error codes */ ++#define HCI_SUCCESS 0x00 ++#define HCI_ERR_ILLEGAL_COMMAND 0x01 ++#define HCI_ERR_NO_CONNECTION 0x02 ++#define HCI_ERR_MEMORY_FULL 0x07 ++#define HCI_ERR_CONNECTION_TIMEOUT 0x08 ++#define HCI_ERR_MAX_NUM_OF_CONNECTIONS 0x09 ++#define HCI_ERR_CONNECTION_EXISTS 0x0B ++#define HCI_ERR_CONNECTION_DISALLOWED 0x0C ++#define HCI_ERR_CONNECTION_ACCEPT_TIMEOUT 0x10 ++#define HCI_ERR_UNSUPPORTED_VALUE 0x11 ++#define HCI_ERR_ILLEGAL_PARAMETER_FMT 0x12 ++#define HCI_ERR_CONN_TERM_BY_LOCAL_HOST 0x16 ++#define HCI_ERR_UNSPECIFIED 0x1F ++#define HCI_ERR_UNIT_KEY_USED 0x26 ++#define HCI_ERR_QOS_REJECTED 0x2D ++#define HCI_ERR_PARAM_OUT_OF_RANGE 0x30 ++#define HCI_ERR_NO_SUITABLE_CHANNEL 0x39 ++#define HCI_ERR_CHANNEL_MOVE 0xFF ++ ++/* AMP HCI ACL Data packet format */ ++typedef BWL_PRE_PACKED_STRUCT struct amp_hci_ACL_data { ++ uint16 handle; /* 12-bit connection handle + 2-bit PB and 2-bit BC flags */ ++ uint16 dlen; /* data total length */ ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT amp_hci_ACL_data_t; ++ ++#define HCI_ACL_DATA_PREAMBLE_SIZE OFFSETOF(amp_hci_ACL_data_t, data) ++ ++#define HCI_ACL_DATA_BC_FLAGS (0x0 << 14) ++#define HCI_ACL_DATA_PB_FLAGS (0x3 << 12) ++ ++#define HCI_ACL_DATA_HANDLE(handle) ((handle) & 0x0fff) ++#define HCI_ACL_DATA_FLAGS(handle) ((handle) >> 12) ++ ++/* AMP Activity Report packet formats */ ++typedef BWL_PRE_PACKED_STRUCT struct amp_hci_activity_report { ++ uint8 ScheduleKnown; ++ uint8 NumReports; ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT amp_hci_activity_report_t; ++ ++typedef BWL_PRE_PACKED_STRUCT struct amp_hci_activity_report_triple { ++ uint32 StartTime; ++ uint32 Duration; ++ uint32 Periodicity; ++} BWL_POST_PACKED_STRUCT amp_hci_activity_report_triple_t; ++ ++#define HCI_AR_SCHEDULE_KNOWN 0x01 ++ ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _bt_amp_hci_h_ */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/proto/eapol.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/proto/eapol.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/proto/eapol.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/proto/eapol.h 2014-02-15 00:43:44.793014092 +0100 +@@ -0,0 +1,193 @@ ++/* ++ * 802.1x EAPOL definitions ++ * ++ * See ++ * IEEE Std 802.1X-2001 ++ * IEEE 802.1X RADIUS Usage Guidelines ++ * ++ * Copyright (C) 2002 Broadcom Corporation ++ * ++ * $Id: eapol.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _eapol_h_ ++#define _eapol_h_ ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++#include ++ ++/* EAPOL for 802.3/Ethernet */ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ struct ether_header eth; /* 802.3/Ethernet header */ ++ unsigned char version; /* EAPOL protocol version */ ++ unsigned char type; /* EAPOL type */ ++ unsigned short length; /* Length of body */ ++ unsigned char body[1]; /* Body (optional) */ ++} BWL_POST_PACKED_STRUCT eapol_header_t; ++ ++#define EAPOL_HEADER_LEN 18 ++ ++typedef struct { ++ unsigned char version; /* EAPOL protocol version */ ++ unsigned char type; /* EAPOL type */ ++ unsigned short length; /* Length of body */ ++} eapol_hdr_t; ++ ++#define EAPOL_HDR_LEN 4 ++ ++/* EAPOL version */ ++#define WPA2_EAPOL_VERSION 2 ++#define WPA_EAPOL_VERSION 1 ++#define LEAP_EAPOL_VERSION 1 ++#define SES_EAPOL_VERSION 1 ++ ++/* EAPOL types */ ++#define EAP_PACKET 0 ++#define EAPOL_START 1 ++#define EAPOL_LOGOFF 2 ++#define EAPOL_KEY 3 ++#define EAPOL_ASF 4 ++ ++/* EAPOL-Key types */ ++#define EAPOL_RC4_KEY 1 ++#define EAPOL_WPA2_KEY 2 /* 802.11i/WPA2 */ ++#define EAPOL_WPA_KEY 254 /* WPA */ ++ ++/* RC4 EAPOL-Key header field sizes */ ++#define EAPOL_KEY_REPLAY_LEN 8 ++#define EAPOL_KEY_IV_LEN 16 ++#define EAPOL_KEY_SIG_LEN 16 ++ ++/* RC4 EAPOL-Key */ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ unsigned char type; /* Key Descriptor Type */ ++ unsigned short length; /* Key Length (unaligned) */ ++ unsigned char replay[EAPOL_KEY_REPLAY_LEN]; /* Replay Counter */ ++ unsigned char iv[EAPOL_KEY_IV_LEN]; /* Key IV */ ++ unsigned char index; /* Key Flags & Index */ ++ unsigned char signature[EAPOL_KEY_SIG_LEN]; /* Key Signature */ ++ unsigned char key[1]; /* Key (optional) */ ++} BWL_POST_PACKED_STRUCT eapol_key_header_t; ++ ++#define EAPOL_KEY_HEADER_LEN 44 ++ ++/* RC4 EAPOL-Key flags */ ++#define EAPOL_KEY_FLAGS_MASK 0x80 ++#define EAPOL_KEY_BROADCAST 0 ++#define EAPOL_KEY_UNICAST 0x80 ++ ++/* RC4 EAPOL-Key index */ ++#define EAPOL_KEY_INDEX_MASK 0x7f ++ ++/* WPA/802.11i/WPA2 EAPOL-Key header field sizes */ ++#define EAPOL_WPA_KEY_REPLAY_LEN 8 ++#define EAPOL_WPA_KEY_NONCE_LEN 32 ++#define EAPOL_WPA_KEY_IV_LEN 16 ++#define EAPOL_WPA_KEY_RSC_LEN 8 ++#define EAPOL_WPA_KEY_ID_LEN 8 ++#define EAPOL_WPA_KEY_MIC_LEN 16 ++#define EAPOL_WPA_KEY_DATA_LEN (EAPOL_WPA_MAX_KEY_SIZE + AKW_BLOCK_LEN) ++#define EAPOL_WPA_MAX_KEY_SIZE 32 ++ ++/* WPA EAPOL-Key */ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ unsigned char type; /* Key Descriptor Type */ ++ unsigned short key_info; /* Key Information (unaligned) */ ++ unsigned short key_len; /* Key Length (unaligned) */ ++ unsigned char replay[EAPOL_WPA_KEY_REPLAY_LEN]; /* Replay Counter */ ++ unsigned char nonce[EAPOL_WPA_KEY_NONCE_LEN]; /* Nonce */ ++ unsigned char iv[EAPOL_WPA_KEY_IV_LEN]; /* Key IV */ ++ unsigned char rsc[EAPOL_WPA_KEY_RSC_LEN]; /* Key RSC */ ++ unsigned char id[EAPOL_WPA_KEY_ID_LEN]; /* WPA:Key ID, 802.11i/WPA2: Reserved */ ++ unsigned char mic[EAPOL_WPA_KEY_MIC_LEN]; /* Key MIC */ ++ unsigned short data_len; /* Key Data Length */ ++ unsigned char data[EAPOL_WPA_KEY_DATA_LEN]; /* Key data */ ++} BWL_POST_PACKED_STRUCT eapol_wpa_key_header_t; ++ ++#define EAPOL_WPA_KEY_LEN 95 ++ ++/* WPA/802.11i/WPA2 KEY KEY_INFO bits */ ++#define WPA_KEY_DESC_V1 0x01 ++#define WPA_KEY_DESC_V2 0x02 ++#define WPA_KEY_DESC_V3 0x03 ++#define WPA_KEY_PAIRWISE 0x08 ++#define WPA_KEY_INSTALL 0x40 ++#define WPA_KEY_ACK 0x80 ++#define WPA_KEY_MIC 0x100 ++#define WPA_KEY_SECURE 0x200 ++#define WPA_KEY_ERROR 0x400 ++#define WPA_KEY_REQ 0x800 ++ ++#define WPA_KEY_DESC_V2_OR_V3 WPA_KEY_DESC_V2 ++ ++/* WPA-only KEY KEY_INFO bits */ ++#define WPA_KEY_INDEX_0 0x00 ++#define WPA_KEY_INDEX_1 0x10 ++#define WPA_KEY_INDEX_2 0x20 ++#define WPA_KEY_INDEX_3 0x30 ++#define WPA_KEY_INDEX_MASK 0x30 ++#define WPA_KEY_INDEX_SHIFT 0x04 ++ ++/* 802.11i/WPA2-only KEY KEY_INFO bits */ ++#define WPA_KEY_ENCRYPTED_DATA 0x1000 ++ ++/* Key Data encapsulation */ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ uint8 type; ++ uint8 length; ++ uint8 oui[3]; ++ uint8 subtype; ++ uint8 data[1]; ++} BWL_POST_PACKED_STRUCT eapol_wpa2_encap_data_t; ++ ++#define EAPOL_WPA2_ENCAP_DATA_HDR_LEN 6 ++ ++#define WPA2_KEY_DATA_SUBTYPE_GTK 1 ++#define WPA2_KEY_DATA_SUBTYPE_STAKEY 2 ++#define WPA2_KEY_DATA_SUBTYPE_MAC 3 ++#define WPA2_KEY_DATA_SUBTYPE_PMKID 4 ++#define WPA2_KEY_DATA_SUBTYPE_IGTK 9 ++ ++/* GTK encapsulation */ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ uint8 flags; ++ uint8 reserved; ++ uint8 gtk[EAPOL_WPA_MAX_KEY_SIZE]; ++} BWL_POST_PACKED_STRUCT eapol_wpa2_key_gtk_encap_t; ++ ++#define EAPOL_WPA2_KEY_GTK_ENCAP_HDR_LEN 2 ++ ++#define WPA2_GTK_INDEX_MASK 0x03 ++#define WPA2_GTK_INDEX_SHIFT 0x00 ++ ++#define WPA2_GTK_TRANSMIT 0x04 ++ ++/* IGTK encapsulation */ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ uint16 key_id; ++ uint8 ipn[6]; ++ uint8 key[EAPOL_WPA_MAX_KEY_SIZE]; ++} BWL_POST_PACKED_STRUCT eapol_wpa2_key_igtk_encap_t; ++ ++#define EAPOL_WPA2_KEY_IGTK_ENCAP_HDR_LEN 8 ++ ++/* STAKey encapsulation */ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ uint8 reserved[2]; ++ uint8 mac[ETHER_ADDR_LEN]; ++ uint8 stakey[EAPOL_WPA_MAX_KEY_SIZE]; ++} BWL_POST_PACKED_STRUCT eapol_wpa2_key_stakey_encap_t; ++ ++#define WPA2_KEY_DATA_PAD 0xdd ++ ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _eapol_h_ */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/proto/ethernet.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/proto/ethernet.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/proto/ethernet.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/proto/ethernet.h 2014-02-15 00:43:44.793014092 +0100 +@@ -0,0 +1,190 @@ ++/* ++ * From FreeBSD 2.2.7: Fundamental constants relating to ethernet. ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: ethernet.h 309193 2012-01-19 00:03:57Z $ ++ */ ++ ++#ifndef _NET_ETHERNET_H_ /* use native BSD ethernet.h when available */ ++#define _NET_ETHERNET_H_ ++ ++#ifndef _TYPEDEFS_H_ ++#include "typedefs.h" ++#endif ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++ ++/* ++ * The number of bytes in an ethernet (MAC) address. ++ */ ++#define ETHER_ADDR_LEN 6 ++ ++/* ++ * The number of bytes in the type field. ++ */ ++#define ETHER_TYPE_LEN 2 ++ ++/* ++ * The number of bytes in the trailing CRC field. ++ */ ++#define ETHER_CRC_LEN 4 ++ ++/* ++ * The length of the combined header. ++ */ ++#define ETHER_HDR_LEN (ETHER_ADDR_LEN * 2 + ETHER_TYPE_LEN) ++ ++/* ++ * The minimum packet length. ++ */ ++#define ETHER_MIN_LEN 64 ++ ++/* ++ * The minimum packet user data length. ++ */ ++#define ETHER_MIN_DATA 46 ++ ++/* ++ * The maximum packet length. ++ */ ++#define ETHER_MAX_LEN 1518 ++ ++/* ++ * The maximum packet user data length. ++ */ ++#define ETHER_MAX_DATA 1500 ++ ++/* ether types */ ++#define ETHER_TYPE_MIN 0x0600 /* Anything less than MIN is a length */ ++#define ETHER_TYPE_IP 0x0800 /* IP */ ++#define ETHER_TYPE_ARP 0x0806 /* ARP */ ++#define ETHER_TYPE_8021Q 0x8100 /* 802.1Q */ ++#define ETHER_TYPE_IPV6 0x86dd /* IPv6 */ ++#define ETHER_TYPE_BRCM 0x886c /* Broadcom Corp. */ ++#define ETHER_TYPE_802_1X 0x888e /* 802.1x */ ++#define ETHER_TYPE_802_1X_PREAUTH 0x88c7 /* 802.1x preauthentication */ ++#define ETHER_TYPE_WAI 0x88b4 /* WAI */ ++#define ETHER_TYPE_89_0D 0x890d /* 89-0d frame for TDLS */ ++ ++#define ETHER_TYPE_IPV6 0x86dd /* IPV6 */ ++ ++/* Broadcom subtype follows ethertype; First 2 bytes are reserved; Next 2 are subtype; */ ++#define ETHER_BRCM_SUBTYPE_LEN 4 /* Broadcom 4 byte subtype */ ++ ++/* ether header */ ++#define ETHER_DEST_OFFSET (0 * ETHER_ADDR_LEN) /* dest address offset */ ++#define ETHER_SRC_OFFSET (1 * ETHER_ADDR_LEN) /* src address offset */ ++#define ETHER_TYPE_OFFSET (2 * ETHER_ADDR_LEN) /* ether type offset */ ++ ++/* ++ * A macro to validate a length with ++ */ ++#define ETHER_IS_VALID_LEN(foo) \ ++ ((foo) >= ETHER_MIN_LEN && (foo) <= ETHER_MAX_LEN) ++ ++#define ETHER_FILL_MCAST_ADDR_FROM_IP(ea, mgrp_ip) { \ ++ ((uint8 *)ea)[0] = 0x01; \ ++ ((uint8 *)ea)[1] = 0x00; \ ++ ((uint8 *)ea)[2] = 0x5e; \ ++ ((uint8 *)ea)[3] = ((mgrp_ip) >> 16) & 0x7f; \ ++ ((uint8 *)ea)[4] = ((mgrp_ip) >> 8) & 0xff; \ ++ ((uint8 *)ea)[5] = ((mgrp_ip) >> 0) & 0xff; \ ++} ++ ++#ifndef __INCif_etherh /* Quick and ugly hack for VxWorks */ ++/* ++ * Structure of a 10Mb/s Ethernet header. ++ */ ++BWL_PRE_PACKED_STRUCT struct ether_header { ++ uint8 ether_dhost[ETHER_ADDR_LEN]; ++ uint8 ether_shost[ETHER_ADDR_LEN]; ++ uint16 ether_type; ++} BWL_POST_PACKED_STRUCT; ++ ++/* ++ * Structure of a 48-bit Ethernet address. ++ */ ++BWL_PRE_PACKED_STRUCT struct ether_addr { ++ uint8 octet[ETHER_ADDR_LEN]; ++} BWL_POST_PACKED_STRUCT; ++#endif /* !__INCif_etherh Quick and ugly hack for VxWorks */ ++ ++/* ++ * Takes a pointer, set, test, clear, toggle locally admininistered ++ * address bit in the 48-bit Ethernet address. ++ */ ++#define ETHER_SET_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] | 2)) ++#define ETHER_IS_LOCALADDR(ea) (((uint8 *)(ea))[0] & 2) ++#define ETHER_CLR_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] & 0xfd)) ++#define ETHER_TOGGLE_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] ^ 2)) ++ ++/* Takes a pointer, marks unicast address bit in the MAC address */ ++#define ETHER_SET_UNICAST(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] & ~1)) ++ ++/* ++ * Takes a pointer, returns true if a 48-bit multicast address ++ * (including broadcast, since it is all ones) ++ */ ++#define ETHER_ISMULTI(ea) (((const uint8 *)(ea))[0] & 1) ++ ++ ++/* compare two ethernet addresses - assumes the pointers can be referenced as shorts */ ++#define ether_cmp(a, b) (!(((short*)(a))[0] == ((short*)(b))[0]) | \ ++ !(((short*)(a))[1] == ((short*)(b))[1]) | \ ++ !(((short*)(a))[2] == ((short*)(b))[2])) ++ ++/* copy an ethernet address - assumes the pointers can be referenced as shorts */ ++#define ether_copy(s, d) { \ ++ ((short*)(d))[0] = ((const short*)(s))[0]; \ ++ ((short*)(d))[1] = ((const short*)(s))[1]; \ ++ ((short*)(d))[2] = ((const short*)(s))[2]; } ++ ++ ++static const struct ether_addr ether_bcast = {{255, 255, 255, 255, 255, 255}}; ++static const struct ether_addr ether_null = {{0, 0, 0, 0, 0, 0}}; ++ ++#define ETHER_ISBCAST(ea) ((((uint8 *)(ea))[0] & \ ++ ((uint8 *)(ea))[1] & \ ++ ((uint8 *)(ea))[2] & \ ++ ((uint8 *)(ea))[3] & \ ++ ((uint8 *)(ea))[4] & \ ++ ((uint8 *)(ea))[5]) == 0xff) ++#define ETHER_ISNULLADDR(ea) ((((uint8 *)(ea))[0] | \ ++ ((uint8 *)(ea))[1] | \ ++ ((uint8 *)(ea))[2] | \ ++ ((uint8 *)(ea))[3] | \ ++ ((uint8 *)(ea))[4] | \ ++ ((uint8 *)(ea))[5]) == 0) ++ ++#define ETHER_MOVE_HDR(d, s) \ ++do { \ ++ struct ether_header t; \ ++ t = *(struct ether_header *)(s); \ ++ *(struct ether_header *)(d) = t; \ ++} while (0) ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _NET_ETHERNET_H_ */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/proto/p2p.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/proto/p2p.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/proto/p2p.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/proto/p2p.h 2014-02-15 00:43:44.793014092 +0100 +@@ -0,0 +1,579 @@ ++/* ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * Fundamental types and constants relating to WFA P2P (aka WiFi Direct) ++ * ++ * $Id: p2p.h 356417 2012-09-12 16:41:24Z $ ++ */ ++ ++#ifndef _P2P_H_ ++#define _P2P_H_ ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++#include ++#include ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++ ++/* WiFi P2P OUI values */ ++#define P2P_OUI WFA_OUI /* WiFi P2P OUI */ ++#define P2P_VER WFA_OUI_TYPE_P2P /* P2P version: 9=WiFi P2P v1.0 */ ++ ++#define P2P_IE_ID 0xdd /* P2P IE element ID */ ++ ++/* WiFi P2P IE */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_ie { ++ uint8 id; /* IE ID: 0xDD */ ++ uint8 len; /* IE length */ ++ uint8 OUI[3]; /* WiFi P2P specific OUI: P2P_OUI */ ++ uint8 oui_type; /* Identifies P2P version: P2P_VER */ ++ uint8 subelts[1]; /* variable length subelements */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_ie wifi_p2p_ie_t; ++ ++#define P2P_IE_FIXED_LEN 6 ++ ++#define P2P_ATTR_ID_OFF 0 ++#define P2P_ATTR_LEN_OFF 1 ++#define P2P_ATTR_DATA_OFF 3 ++ ++#define P2P_ATTR_ID_LEN 1 /* ID filed length */ ++#define P2P_ATTR_LEN_LEN 2 /* length field length */ ++#define P2P_ATTR_HDR_LEN 3 /* ID + 2-byte length field spec 1.02 */ ++ ++/* P2P IE Subelement IDs from WiFi P2P Technical Spec 1.00 */ ++#define P2P_SEID_STATUS 0 /* Status */ ++#define P2P_SEID_MINOR_RC 1 /* Minor Reason Code */ ++#define P2P_SEID_P2P_INFO 2 /* P2P Capability (capabilities info) */ ++#define P2P_SEID_DEV_ID 3 /* P2P Device ID */ ++#define P2P_SEID_INTENT 4 /* Group Owner Intent */ ++#define P2P_SEID_CFG_TIMEOUT 5 /* Configuration Timeout */ ++#define P2P_SEID_CHANNEL 6 /* Channel */ ++#define P2P_SEID_GRP_BSSID 7 /* P2P Group BSSID */ ++#define P2P_SEID_XT_TIMING 8 /* Extended Listen Timing */ ++#define P2P_SEID_INTINTADDR 9 /* Intended P2P Interface Address */ ++#define P2P_SEID_P2P_MGBTY 10 /* P2P Manageability */ ++#define P2P_SEID_CHAN_LIST 11 /* Channel List */ ++#define P2P_SEID_ABSENCE 12 /* Notice of Absence */ ++#define P2P_SEID_DEV_INFO 13 /* Device Info */ ++#define P2P_SEID_GROUP_INFO 14 /* Group Info */ ++#define P2P_SEID_GROUP_ID 15 /* Group ID */ ++#define P2P_SEID_P2P_IF 16 /* P2P Interface */ ++#define P2P_SEID_OP_CHANNEL 17 /* Operating Channel */ ++#define P2P_SEID_INVITE_FLAGS 18 /* Invitation Flags */ ++#define P2P_SEID_VNDR 221 /* Vendor-specific subelement */ ++ ++#define P2P_SE_VS_ID_SERVICES 0x1b /* BRCM proprietary subel: L2 Services */ ++ ++ ++/* WiFi P2P IE subelement: P2P Capability (capabilities info) */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_info_se_s { ++ uint8 eltId; /* SE ID: P2P_SEID_P2P_INFO */ ++ uint8 len[2]; /* SE length not including eltId, len fields */ ++ uint8 dev; /* Device Capability Bitmap */ ++ uint8 group; /* Group Capability Bitmap */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_info_se_s wifi_p2p_info_se_t; ++ ++/* P2P Capability subelement's Device Capability Bitmap bit values */ ++#define P2P_CAPSE_DEV_SERVICE_DIS 0x1 /* Service Discovery */ ++#define P2P_CAPSE_DEV_CLIENT_DIS 0x2 /* Client Discoverability */ ++#define P2P_CAPSE_DEV_CONCURRENT 0x4 /* Concurrent Operation */ ++#define P2P_CAPSE_DEV_INFRA_MAN 0x8 /* P2P Infrastructure Managed */ ++#define P2P_CAPSE_DEV_LIMIT 0x10 /* P2P Device Limit */ ++#define P2P_CAPSE_INVITE_PROC 0x20 /* P2P Invitation Procedure */ ++ ++/* P2P Capability subelement's Group Capability Bitmap bit values */ ++#define P2P_CAPSE_GRP_OWNER 0x1 /* P2P Group Owner */ ++#define P2P_CAPSE_PERSIST_GRP 0x2 /* Persistent P2P Group */ ++#define P2P_CAPSE_GRP_LIMIT 0x4 /* P2P Group Limit */ ++#define P2P_CAPSE_GRP_INTRA_BSS 0x8 /* Intra-BSS Distribution */ ++#define P2P_CAPSE_GRP_X_CONNECT 0x10 /* Cross Connection */ ++#define P2P_CAPSE_GRP_PERSISTENT 0x20 /* Persistent Reconnect */ ++#define P2P_CAPSE_GRP_FORMATION 0x40 /* Group Formation */ ++ ++ ++/* WiFi P2P IE subelement: Group Owner Intent */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_intent_se_s { ++ uint8 eltId; /* SE ID: P2P_SEID_INTENT */ ++ uint8 len[2]; /* SE length not including eltId, len fields */ ++ uint8 intent; /* Intent Value 0...15 (0=legacy 15=master only) */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_intent_se_s wifi_p2p_intent_se_t; ++ ++/* WiFi P2P IE subelement: Configuration Timeout */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_cfg_tmo_se_s { ++ uint8 eltId; /* SE ID: P2P_SEID_CFG_TIMEOUT */ ++ uint8 len[2]; /* SE length not including eltId, len fields */ ++ uint8 go_tmo; /* GO config timeout in units of 10 ms */ ++ uint8 client_tmo; /* Client config timeout in units of 10 ms */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_cfg_tmo_se_s wifi_p2p_cfg_tmo_se_t; ++ ++/* WiFi P2P IE subelement: Listen Channel */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_listen_channel_se_s { ++ uint8 eltId; /* SE ID: P2P_SEID_CHANNEL */ ++ uint8 len[2]; /* SE length not including eltId, len fields */ ++ uint8 country[3]; /* Country String */ ++ uint8 op_class; /* Operating Class */ ++ uint8 channel; /* Channel */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_listen_channel_se_s wifi_p2p_listen_channel_se_t; ++ ++/* WiFi P2P IE subelement: P2P Group BSSID */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_grp_bssid_se_s { ++ uint8 eltId; /* SE ID: P2P_SEID_GRP_BSSID */ ++ uint8 len[2]; /* SE length not including eltId, len fields */ ++ uint8 mac[6]; /* P2P group bssid */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_grp_bssid_se_s wifi_p2p_grp_bssid_se_t; ++ ++/* WiFi P2P IE subelement: P2P Group ID */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_grp_id_se_s { ++ uint8 eltId; /* SE ID: P2P_SEID_GROUP_ID */ ++ uint8 len[2]; /* SE length not including eltId, len fields */ ++ uint8 mac[6]; /* P2P device address */ ++ uint8 ssid[1]; /* ssid. device id. variable length */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_grp_id_se_s wifi_p2p_grp_id_se_t; ++ ++/* WiFi P2P IE subelement: P2P Interface */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_intf_se_s { ++ uint8 eltId; /* SE ID: P2P_SEID_P2P_IF */ ++ uint8 len[2]; /* SE length not including eltId, len fields */ ++ uint8 mac[6]; /* P2P device address */ ++ uint8 ifaddrs; /* P2P Interface Address count */ ++ uint8 ifaddr[1][6]; /* P2P Interface Address list */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_intf_se_s wifi_p2p_intf_se_t; ++ ++/* WiFi P2P IE subelement: Status */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_status_se_s { ++ uint8 eltId; /* SE ID: P2P_SEID_STATUS */ ++ uint8 len[2]; /* SE length not including eltId, len fields */ ++ uint8 status; /* Status Code: P2P_STATSE_* */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_status_se_s wifi_p2p_status_se_t; ++ ++/* Status subelement Status Code definitions */ ++#define P2P_STATSE_SUCCESS 0 ++ /* Success */ ++#define P2P_STATSE_FAIL_INFO_CURR_UNAVAIL 1 ++ /* Failed, information currently unavailable */ ++#define P2P_STATSE_PASSED_UP P2P_STATSE_FAIL_INFO_CURR_UNAVAIL ++ /* Old name for above in P2P spec 1.08 and older */ ++#define P2P_STATSE_FAIL_INCOMPAT_PARAMS 2 ++ /* Failed, incompatible parameters */ ++#define P2P_STATSE_FAIL_LIMIT_REACHED 3 ++ /* Failed, limit reached */ ++#define P2P_STATSE_FAIL_INVALID_PARAMS 4 ++ /* Failed, invalid parameters */ ++#define P2P_STATSE_FAIL_UNABLE_TO_ACCOM 5 ++ /* Failed, unable to accomodate request */ ++#define P2P_STATSE_FAIL_PROTO_ERROR 6 ++ /* Failed, previous protocol error or disruptive behaviour */ ++#define P2P_STATSE_FAIL_NO_COMMON_CHAN 7 ++ /* Failed, no common channels */ ++#define P2P_STATSE_FAIL_UNKNOWN_GROUP 8 ++ /* Failed, unknown P2P Group */ ++#define P2P_STATSE_FAIL_INTENT 9 ++ /* Failed, both peers indicated Intent 15 in GO Negotiation */ ++#define P2P_STATSE_FAIL_INCOMPAT_PROVIS 10 ++ /* Failed, incompatible provisioning method */ ++#define P2P_STATSE_FAIL_USER_REJECT 11 ++ /* Failed, rejected by user */ ++ ++/* WiFi P2P IE attribute: Extended Listen Timing */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_ext_se_s { ++ uint8 eltId; /* ID: P2P_SEID_EXT_TIMING */ ++ uint8 len[2]; /* length not including eltId, len fields */ ++ uint8 avail[2]; /* availibility period */ ++ uint8 interval[2]; /* availibility interval */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_ext_se_s wifi_p2p_ext_se_t; ++ ++#define P2P_EXT_MIN 10 /* minimum 10ms */ ++ ++/* WiFi P2P IE subelement: Intended P2P Interface Address */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_intintad_se_s { ++ uint8 eltId; /* SE ID: P2P_SEID_INTINTADDR */ ++ uint8 len[2]; /* SE length not including eltId, len fields */ ++ uint8 mac[6]; /* intended P2P interface MAC address */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_intintad_se_s wifi_p2p_intintad_se_t; ++ ++/* WiFi P2P IE subelement: Channel */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_channel_se_s { ++ uint8 eltId; /* SE ID: P2P_SEID_STATUS */ ++ uint8 len[2]; /* SE length not including eltId, len fields */ ++ uint8 band; /* Regulatory Class (band) */ ++ uint8 channel; /* Channel */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_channel_se_s wifi_p2p_channel_se_t; ++ ++ ++/* Channel Entry structure within the Channel List SE */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_chanlist_entry_s { ++ uint8 band; /* Regulatory Class (band) */ ++ uint8 num_channels; /* # of channels in the channel list */ ++ uint8 channels[WL_NUMCHANNELS]; /* Channel List */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_chanlist_entry_s wifi_p2p_chanlist_entry_t; ++#define WIFI_P2P_CHANLIST_SE_MAX_ENTRIES 2 ++ ++/* WiFi P2P IE subelement: Channel List */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_chanlist_se_s { ++ uint8 eltId; /* SE ID: P2P_SEID_CHAN_LIST */ ++ uint8 len[2]; /* SE length not including eltId, len fields */ ++ uint8 country[3]; /* Country String */ ++ uint8 num_entries; /* # of channel entries */ ++ wifi_p2p_chanlist_entry_t entries[WIFI_P2P_CHANLIST_SE_MAX_ENTRIES]; ++ /* Channel Entry List */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_chanlist_se_s wifi_p2p_chanlist_se_t; ++ ++/* WiFi Primary Device Type structure */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_pri_devtype_s { ++ uint16 cat_id; /* Category ID */ ++ uint8 OUI[3]; /* WFA OUI: 0x0050F2 */ ++ uint8 oui_type; /* WPS_OUI_TYPE */ ++ uint16 sub_cat_id; /* Sub Category ID */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_pri_devtype_s wifi_p2p_pri_devtype_t; ++ ++/* WiFi P2P IE's Device Info subelement */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_devinfo_se_s { ++ uint8 eltId; /* SE ID: P2P_SEID_DEVINFO */ ++ uint8 len[2]; /* SE length not including eltId, len fields */ ++ uint8 mac[6]; /* P2P Device MAC address */ ++ uint16 wps_cfg_meths; /* Config Methods: reg_prototlv.h WPS_CONFMET_* */ ++ uint8 pri_devtype[8]; /* Primary Device Type */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_devinfo_se_s wifi_p2p_devinfo_se_t; ++ ++#define P2P_DEV_TYPE_LEN 8 ++ ++/* WiFi P2P IE's Group Info subelement Client Info Descriptor */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_cid_fixed_s { ++ uint8 len; ++ uint8 devaddr[ETHER_ADDR_LEN]; /* P2P Device Address */ ++ uint8 ifaddr[ETHER_ADDR_LEN]; /* P2P Interface Address */ ++ uint8 devcap; /* Device Capability */ ++ uint8 cfg_meths[2]; /* Config Methods: reg_prototlv.h WPS_CONFMET_* */ ++ uint8 pridt[P2P_DEV_TYPE_LEN]; /* Primary Device Type */ ++ uint8 secdts; /* Number of Secondary Device Types */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_cid_fixed_s wifi_p2p_cid_fixed_t; ++ ++/* WiFi P2P IE's Device ID subelement */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_devid_se_s { ++ uint8 eltId; ++ uint8 len[2]; ++ struct ether_addr addr; /* P2P Device MAC address */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_devid_se_s wifi_p2p_devid_se_t; ++ ++/* WiFi P2P IE subelement: P2P Manageability */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_mgbt_se_s { ++ uint8 eltId; /* SE ID: P2P_SEID_P2P_MGBTY */ ++ uint8 len[2]; /* SE length not including eltId, len fields */ ++ uint8 mg_bitmap; /* manageability bitmap */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_mgbt_se_s wifi_p2p_mgbt_se_t; ++/* mg_bitmap field bit values */ ++#define P2P_MGBTSE_P2PDEVMGMT_FLAG 0x1 /* AP supports Managed P2P Device */ ++ ++/* WiFi P2P IE subelement: Group Info */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_grpinfo_se_s { ++ uint8 eltId; /* SE ID: P2P_SEID_GROUP_INFO */ ++ uint8 len[2]; /* SE length not including eltId, len fields */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_grpinfo_se_s wifi_p2p_grpinfo_se_t; ++ ++/* WiFi IE subelement: Operating Channel */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_op_channel_se_s { ++ uint8 eltId; /* SE ID: P2P_SEID_OP_CHANNEL */ ++ uint8 len[2]; /* SE length not including eltId, len fields */ ++ uint8 country[3]; /* Country String */ ++ uint8 op_class; /* Operating Class */ ++ uint8 channel; /* Channel */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_op_channel_se_s wifi_p2p_op_channel_se_t; ++ ++/* WiFi IE subelement: INVITATION FLAGS */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_invite_flags_se_s { ++ uint8 eltId; /* SE ID: P2P_SEID_INVITE_FLAGS */ ++ uint8 len[2]; /* SE length not including eltId, len fields */ ++ uint8 flags; /* Flags */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_invite_flags_se_s wifi_p2p_invite_flags_se_t; ++ ++/* WiFi P2P Action Frame */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_action_frame { ++ uint8 category; /* P2P_AF_CATEGORY */ ++ uint8 OUI[3]; /* OUI - P2P_OUI */ ++ uint8 type; /* OUI Type - P2P_VER */ ++ uint8 subtype; /* OUI Subtype - P2P_AF_* */ ++ uint8 dialog_token; /* nonzero, identifies req/resp tranaction */ ++ uint8 elts[1]; /* Variable length information elements. Max size = ++ * ACTION_FRAME_SIZE - sizeof(this structure) - 1 ++ */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_action_frame wifi_p2p_action_frame_t; ++#define P2P_AF_CATEGORY 0x7f ++ ++#define P2P_AF_FIXED_LEN 7 ++ ++/* WiFi P2P Action Frame OUI Subtypes */ ++#define P2P_AF_NOTICE_OF_ABSENCE 0 /* Notice of Absence */ ++#define P2P_AF_PRESENCE_REQ 1 /* P2P Presence Request */ ++#define P2P_AF_PRESENCE_RSP 2 /* P2P Presence Response */ ++#define P2P_AF_GO_DISC_REQ 3 /* GO Discoverability Request */ ++ ++ ++/* WiFi P2P Public Action Frame */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_pub_act_frame { ++ uint8 category; /* P2P_PUB_AF_CATEGORY */ ++ uint8 action; /* P2P_PUB_AF_ACTION */ ++ uint8 oui[3]; /* P2P_OUI */ ++ uint8 oui_type; /* OUI type - P2P_VER */ ++ uint8 subtype; /* OUI subtype - P2P_TYPE_* */ ++ uint8 dialog_token; /* nonzero, identifies req/rsp transaction */ ++ uint8 elts[1]; /* Variable length information elements. Max size = ++ * ACTION_FRAME_SIZE - sizeof(this structure) - 1 ++ */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_pub_act_frame wifi_p2p_pub_act_frame_t; ++#define P2P_PUB_AF_FIXED_LEN 8 ++#define P2P_PUB_AF_CATEGORY 0x04 ++#define P2P_PUB_AF_ACTION 0x09 ++ ++/* WiFi P2P Public Action Frame OUI Subtypes */ ++#define P2P_PAF_GON_REQ 0 /* Group Owner Negotiation Req */ ++#define P2P_PAF_GON_RSP 1 /* Group Owner Negotiation Rsp */ ++#define P2P_PAF_GON_CONF 2 /* Group Owner Negotiation Confirm */ ++#define P2P_PAF_INVITE_REQ 3 /* P2P Invitation Request */ ++#define P2P_PAF_INVITE_RSP 4 /* P2P Invitation Response */ ++#define P2P_PAF_DEVDIS_REQ 5 /* Device Discoverability Request */ ++#define P2P_PAF_DEVDIS_RSP 6 /* Device Discoverability Response */ ++#define P2P_PAF_PROVDIS_REQ 7 /* Provision Discovery Request */ ++#define P2P_PAF_PROVDIS_RSP 8 /* Provision Discovery Response */ ++#define P2P_PAF_SUBTYPE_INVALID 255 /* Invalid Subtype */ ++ ++/* TODO: Stop using these obsolete aliases for P2P_PAF_GON_* */ ++#define P2P_TYPE_MNREQ P2P_PAF_GON_REQ ++#define P2P_TYPE_MNRSP P2P_PAF_GON_RSP ++#define P2P_TYPE_MNCONF P2P_PAF_GON_CONF ++ ++/* WiFi P2P IE subelement: Notice of Absence */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_noa_desc { ++ uint8 cnt_type; /* Count/Type */ ++ uint32 duration; /* Duration */ ++ uint32 interval; /* Interval */ ++ uint32 start; /* Start Time */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_noa_desc wifi_p2p_noa_desc_t; ++ ++BWL_PRE_PACKED_STRUCT struct wifi_p2p_noa_se { ++ uint8 eltId; /* Subelement ID */ ++ uint8 len[2]; /* Length */ ++ uint8 index; /* Index */ ++ uint8 ops_ctw_parms; /* CTWindow and OppPS Parameters */ ++ wifi_p2p_noa_desc_t desc[1]; /* Notice of Absence Descriptor(s) */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2p_noa_se wifi_p2p_noa_se_t; ++ ++#define P2P_NOA_SE_FIXED_LEN 5 ++ ++/* cnt_type field values */ ++#define P2P_NOA_DESC_CNT_RESERVED 0 /* reserved and should not be used */ ++#define P2P_NOA_DESC_CNT_REPEAT 255 /* continuous schedule */ ++#define P2P_NOA_DESC_TYPE_PREFERRED 1 /* preferred values */ ++#define P2P_NOA_DESC_TYPE_ACCEPTABLE 2 /* acceptable limits */ ++ ++/* ctw_ops_parms field values */ ++#define P2P_NOA_CTW_MASK 0x7f ++#define P2P_NOA_OPS_MASK 0x80 ++#define P2P_NOA_OPS_SHIFT 7 ++ ++#define P2P_CTW_MIN 10 /* minimum 10TU */ ++ ++/* ++ * P2P Service Discovery related ++ */ ++#define P2PSD_ACTION_CATEGORY 0x04 ++ /* Public action frame */ ++#define P2PSD_ACTION_ID_GAS_IREQ 0x0a ++ /* Action value for GAS Initial Request AF */ ++#define P2PSD_ACTION_ID_GAS_IRESP 0x0b ++ /* Action value for GAS Initial Response AF */ ++#define P2PSD_ACTION_ID_GAS_CREQ 0x0c ++ /* Action value for GAS Comback Request AF */ ++#define P2PSD_ACTION_ID_GAS_CRESP 0x0d ++ /* Action value for GAS Comback Response AF */ ++#define P2PSD_AD_EID 0x6c ++ /* Advertisement Protocol IE ID */ ++#define P2PSD_ADP_TUPLE_QLMT_PAMEBI 0x00 ++ /* Query Response Length Limit 7 bits plus PAME-BI 1 bit */ ++#define P2PSD_ADP_PROTO_ID 0x00 ++ /* Advertisement Protocol ID. Always 0 for P2P SD */ ++#define P2PSD_GAS_OUI P2P_OUI ++ /* WFA OUI */ ++#define P2PSD_GAS_OUI_SUBTYPE P2P_VER ++ /* OUI Subtype for GAS IE */ ++#define P2PSD_GAS_NQP_INFOID 0xDDDD ++ /* NQP Query Info ID: 56797 */ ++#define P2PSD_GAS_COMEBACKDEALY 0x00 ++ /* Not used in the Native GAS protocol */ ++ ++/* Service Protocol Type */ ++typedef enum p2psd_svc_protype { ++ SVC_RPOTYPE_ALL = 0, ++ SVC_RPOTYPE_BONJOUR = 1, ++ SVC_RPOTYPE_UPNP = 2, ++ SVC_RPOTYPE_WSD = 3, ++ SVC_RPOTYPE_VENDOR = 255 ++} p2psd_svc_protype_t; ++ ++/* Service Discovery response status code */ ++typedef enum { ++ P2PSD_RESP_STATUS_SUCCESS = 0, ++ P2PSD_RESP_STATUS_PROTYPE_NA = 1, ++ P2PSD_RESP_STATUS_DATA_NA = 2, ++ P2PSD_RESP_STATUS_BAD_REQUEST = 3 ++} p2psd_resp_status_t; ++ ++/* Advertisement Protocol IE tuple field */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2psd_adp_tpl { ++ uint8 llm_pamebi; /* Query Response Length Limit bit 0-6, set to 0 plus ++ * Pre-Associated Message Exchange BSSID Independent bit 7, set to 0 ++ */ ++ uint8 adp_id; /* Advertisement Protocol ID: 0 for NQP Native Query Protocol */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2psd_adp_tpl wifi_p2psd_adp_tpl_t; ++ ++/* Advertisement Protocol IE */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2psd_adp_ie { ++ uint8 id; /* IE ID: 0x6c - 108 */ ++ uint8 len; /* IE length */ ++ wifi_p2psd_adp_tpl_t adp_tpl; /* Advertisement Protocol Tuple field. Only one ++ * tuple is defined for P2P Service Discovery ++ */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2psd_adp_ie wifi_p2psd_adp_ie_t; ++ ++/* NQP Vendor-specific Content */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2psd_nqp_query_vsc { ++ uint8 oui_subtype; /* OUI Subtype: 0x09 */ ++ uint16 svc_updi; /* Service Update Indicator */ ++ uint8 svc_tlvs[1]; /* wifi_p2psd_qreq_tlv_t type for service request, ++ * wifi_p2psd_qresp_tlv_t type for service response ++ */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2psd_nqp_query_vsc wifi_p2psd_nqp_query_vsc_t; ++ ++/* Service Request TLV */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2psd_qreq_tlv { ++ uint16 len; /* Length: 5 plus size of Query Data */ ++ uint8 svc_prot; /* Service Protocol Type */ ++ uint8 svc_tscid; /* Service Transaction ID */ ++ uint8 query_data[1]; /* Query Data, passed in from above Layer 2 */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2psd_qreq_tlv wifi_p2psd_qreq_tlv_t; ++ ++/* Query Request Frame, defined in generic format, instead of NQP specific */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2psd_qreq_frame { ++ uint16 info_id; /* Info ID: 0xDDDD */ ++ uint16 len; /* Length of service request TLV, 5 plus the size of request data */ ++ uint8 oui[3]; /* WFA OUI: 0x0050F2 */ ++ uint8 qreq_vsc[1]; /* Vendor-specific Content: wifi_p2psd_nqp_query_vsc_t type for NQP */ ++ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2psd_qreq_frame wifi_p2psd_qreq_frame_t; ++ ++/* GAS Initial Request AF body, "elts" in wifi_p2p_pub_act_frame */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2psd_gas_ireq_frame { ++ wifi_p2psd_adp_ie_t adp_ie; /* Advertisement Protocol IE */ ++ uint16 qreq_len; /* Query Request Length */ ++ uint8 qreq_frm[1]; /* Query Request Frame wifi_p2psd_qreq_frame_t */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2psd_gas_ireq_frame wifi_p2psd_gas_ireq_frame_t; ++ ++/* Service Response TLV */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2psd_qresp_tlv { ++ uint16 len; /* Length: 5 plus size of Query Data */ ++ uint8 svc_prot; /* Service Protocol Type */ ++ uint8 svc_tscid; /* Service Transaction ID */ ++ uint8 status; /* Value defined in Table 57 of P2P spec. */ ++ uint8 query_data[1]; /* Response Data, passed in from above Layer 2 */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2psd_qresp_tlv wifi_p2psd_qresp_tlv_t; ++ ++/* Query Response Frame, defined in generic format, instead of NQP specific */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2psd_qresp_frame { ++ uint16 info_id; /* Info ID: 0xDDDD */ ++ uint16 len; /* Lenth of service response TLV, 6 plus the size of resp data */ ++ uint8 oui[3]; /* WFA OUI: 0x0050F2 */ ++ uint8 qresp_vsc[1]; /* Vendor-specific Content: wifi_p2psd_qresp_tlv_t type for NQP */ ++ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2psd_qresp_frame wifi_p2psd_qresp_frame_t; ++ ++/* GAS Initial Response AF body, "elts" in wifi_p2p_pub_act_frame */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2psd_gas_iresp_frame { ++ uint16 status; /* Value defined in Table 7-23 of IEEE P802.11u */ ++ uint16 cb_delay; /* GAS Comeback Delay */ ++ wifi_p2psd_adp_ie_t adp_ie; /* Advertisement Protocol IE */ ++ uint16 qresp_len; /* Query Response Length */ ++ uint8 qresp_frm[1]; /* Query Response Frame wifi_p2psd_qresp_frame_t */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2psd_gas_iresp_frame wifi_p2psd_gas_iresp_frame_t; ++ ++/* GAS Comeback Response AF body, "elts" in wifi_p2p_pub_act_frame */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2psd_gas_cresp_frame { ++ uint16 status; /* Value defined in Table 7-23 of IEEE P802.11u */ ++ uint8 fragment_id; /* Fragmentation ID */ ++ uint16 cb_delay; /* GAS Comeback Delay */ ++ wifi_p2psd_adp_ie_t adp_ie; /* Advertisement Protocol IE */ ++ uint16 qresp_len; /* Query Response Length */ ++ uint8 qresp_frm[1]; /* Query Response Frame wifi_p2psd_qresp_frame_t */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2psd_gas_cresp_frame wifi_p2psd_gas_cresp_frame_t; ++ ++/* Wi-Fi GAS Public Action Frame */ ++BWL_PRE_PACKED_STRUCT struct wifi_p2psd_gas_pub_act_frame { ++ uint8 category; /* 0x04 Public Action Frame */ ++ uint8 action; /* 0x6c Advertisement Protocol */ ++ uint8 dialog_token; /* nonzero, identifies req/rsp transaction */ ++ uint8 query_data[1]; /* Query Data. wifi_p2psd_gas_ireq_frame_t ++ * or wifi_p2psd_gas_iresp_frame_t format ++ */ ++} BWL_POST_PACKED_STRUCT; ++typedef struct wifi_p2psd_gas_pub_act_frame wifi_p2psd_gas_pub_act_frame_t; ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _P2P_H_ */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/proto/sdspi.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/proto/sdspi.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/proto/sdspi.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/proto/sdspi.h 2014-02-15 00:43:44.793014092 +0100 +@@ -0,0 +1,75 @@ ++/* ++ * SD-SPI Protocol Standard ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: sdspi.h 241182 2011-02-17 21:50:03Z $ ++ */ ++#ifndef _SD_SPI_H ++#define _SD_SPI_H ++ ++#define SPI_START_M BITFIELD_MASK(1) /* Bit [31] - Start Bit */ ++#define SPI_START_S 31 ++#define SPI_DIR_M BITFIELD_MASK(1) /* Bit [30] - Direction */ ++#define SPI_DIR_S 30 ++#define SPI_CMD_INDEX_M BITFIELD_MASK(6) /* Bits [29:24] - Command number */ ++#define SPI_CMD_INDEX_S 24 ++#define SPI_RW_M BITFIELD_MASK(1) /* Bit [23] - Read=0, Write=1 */ ++#define SPI_RW_S 23 ++#define SPI_FUNC_M BITFIELD_MASK(3) /* Bits [22:20] - Function Number */ ++#define SPI_FUNC_S 20 ++#define SPI_RAW_M BITFIELD_MASK(1) /* Bit [19] - Read After Wr */ ++#define SPI_RAW_S 19 ++#define SPI_STUFF_M BITFIELD_MASK(1) /* Bit [18] - Stuff bit */ ++#define SPI_STUFF_S 18 ++#define SPI_BLKMODE_M BITFIELD_MASK(1) /* Bit [19] - Blockmode 1=blk */ ++#define SPI_BLKMODE_S 19 ++#define SPI_OPCODE_M BITFIELD_MASK(1) /* Bit [18] - OP Code */ ++#define SPI_OPCODE_S 18 ++#define SPI_ADDR_M BITFIELD_MASK(17) /* Bits [17:1] - Address */ ++#define SPI_ADDR_S 1 ++#define SPI_STUFF0_M BITFIELD_MASK(1) /* Bit [0] - Stuff bit */ ++#define SPI_STUFF0_S 0 ++ ++#define SPI_RSP_START_M BITFIELD_MASK(1) /* Bit [7] - Start Bit (always 0) */ ++#define SPI_RSP_START_S 7 ++#define SPI_RSP_PARAM_ERR_M BITFIELD_MASK(1) /* Bit [6] - Parameter Error */ ++#define SPI_RSP_PARAM_ERR_S 6 ++#define SPI_RSP_RFU5_M BITFIELD_MASK(1) /* Bit [5] - RFU (Always 0) */ ++#define SPI_RSP_RFU5_S 5 ++#define SPI_RSP_FUNC_ERR_M BITFIELD_MASK(1) /* Bit [4] - Function number error */ ++#define SPI_RSP_FUNC_ERR_S 4 ++#define SPI_RSP_CRC_ERR_M BITFIELD_MASK(1) /* Bit [3] - COM CRC Error */ ++#define SPI_RSP_CRC_ERR_S 3 ++#define SPI_RSP_ILL_CMD_M BITFIELD_MASK(1) /* Bit [2] - Illegal Command error */ ++#define SPI_RSP_ILL_CMD_S 2 ++#define SPI_RSP_RFU1_M BITFIELD_MASK(1) /* Bit [1] - RFU (Always 0) */ ++#define SPI_RSP_RFU1_S 1 ++#define SPI_RSP_IDLE_M BITFIELD_MASK(1) /* Bit [0] - In idle state */ ++#define SPI_RSP_IDLE_S 0 ++ ++/* SD-SPI Protocol Definitions */ ++#define SDSPI_COMMAND_LEN 6 /* Number of bytes in an SD command */ ++#define SDSPI_START_BLOCK 0xFE /* SD Start Block Token */ ++#define SDSPI_IDLE_PAD 0xFF /* SD-SPI idle value for MOSI */ ++#define SDSPI_START_BIT_MASK 0x80 ++ ++#endif /* _SD_SPI_H */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/proto/vlan.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/proto/vlan.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/proto/vlan.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/proto/vlan.h 2014-02-15 00:43:44.793014092 +0100 +@@ -0,0 +1,69 @@ ++/* ++ * 802.1Q VLAN protocol definitions ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: vlan.h 241182 2011-02-17 21:50:03Z $ ++ */ ++ ++#ifndef _vlan_h_ ++#define _vlan_h_ ++ ++#ifndef _TYPEDEFS_H_ ++#include ++#endif ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++#define VLAN_VID_MASK 0xfff /* low 12 bits are vlan id */ ++#define VLAN_CFI_SHIFT 12 /* canonical format indicator bit */ ++#define VLAN_PRI_SHIFT 13 /* user priority */ ++ ++#define VLAN_PRI_MASK 7 /* 3 bits of priority */ ++ ++#define VLAN_TAG_LEN 4 ++#define VLAN_TAG_OFFSET (2 * ETHER_ADDR_LEN) /* offset in Ethernet II packet only */ ++ ++#define VLAN_TPID 0x8100 /* VLAN ethertype/Tag Protocol ID */ ++ ++struct ethervlan_header { ++ uint8 ether_dhost[ETHER_ADDR_LEN]; ++ uint8 ether_shost[ETHER_ADDR_LEN]; ++ uint16 vlan_type; /* 0x8100 */ ++ uint16 vlan_tag; /* priority, cfi and vid */ ++ uint16 ether_type; ++}; ++ ++#define ETHERVLAN_HDR_LEN (ETHER_HDR_LEN + VLAN_TAG_LEN) ++ ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#define ETHERVLAN_MOVE_HDR(d, s) \ ++do { \ ++ struct ethervlan_header t; \ ++ t = *(struct ethervlan_header *)(s); \ ++ *(struct ethervlan_header *)(d) = t; \ ++} while (0) ++ ++#endif /* _vlan_h_ */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/proto/wpa.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/proto/wpa.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/proto/wpa.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/proto/wpa.h 2014-02-15 00:43:44.793014092 +0100 +@@ -0,0 +1,206 @@ ++/* ++ * Fundamental types and constants relating to WPA ++ * ++ * Copyright (C) 1999-2012, Broadcom Corporation ++ * ++ * Unless you and Broadcom execute a separate written software license ++ * agreement governing use of this software, this software is licensed to you ++ * under the terms of the GNU General Public License version 2 (the "GPL"), ++ * available at http://www.broadcom.com/licenses/GPLv2.php, with the ++ * following added to such license: ++ * ++ * As a special exception, the copyright holders of this software give you ++ * permission to link this software with independent modules, and to copy and ++ * distribute the resulting executable under terms of your choice, provided that ++ * you also meet, for each linked independent module, the terms and conditions of ++ * the license of that module. An independent module is a module which is not ++ * derived from this software. The special exception does not apply to any ++ * modifications of the software. ++ * ++ * Notwithstanding the above, under no circumstances may you combine this ++ * software in any way with any other Broadcom software provided under a license ++ * other than the GPL, without Broadcom's express prior written consent. ++ * ++ * $Id: wpa.h 261155 2011-05-23 23:51:32Z $ ++ */ ++ ++#ifndef _proto_wpa_h_ ++#define _proto_wpa_h_ ++ ++#include ++#include ++ ++ ++/* This marks the start of a packed structure section. */ ++#include ++ ++/* Reason Codes */ ++ ++/* 13 through 23 taken from IEEE Std 802.11i-2004 */ ++#define DOT11_RC_INVALID_WPA_IE 13 /* Invalid info. element */ ++#define DOT11_RC_MIC_FAILURE 14 /* Michael failure */ ++#define DOT11_RC_4WH_TIMEOUT 15 /* 4-way handshake timeout */ ++#define DOT11_RC_GTK_UPDATE_TIMEOUT 16 /* Group key update timeout */ ++#define DOT11_RC_WPA_IE_MISMATCH 17 /* WPA IE in 4-way handshake differs from ++ * (re-)assoc. request/probe response ++ */ ++#define DOT11_RC_INVALID_MC_CIPHER 18 /* Invalid multicast cipher */ ++#define DOT11_RC_INVALID_UC_CIPHER 19 /* Invalid unicast cipher */ ++#define DOT11_RC_INVALID_AKMP 20 /* Invalid authenticated key management protocol */ ++#define DOT11_RC_BAD_WPA_VERSION 21 /* Unsupported WPA version */ ++#define DOT11_RC_INVALID_WPA_CAP 22 /* Invalid WPA IE capabilities */ ++#define DOT11_RC_8021X_AUTH_FAIL 23 /* 802.1X authentication failure */ ++ ++#define WPA2_PMKID_LEN 16 ++ ++/* WPA IE fixed portion */ ++typedef BWL_PRE_PACKED_STRUCT struct ++{ ++ uint8 tag; /* TAG */ ++ uint8 length; /* TAG length */ ++ uint8 oui[3]; /* IE OUI */ ++ uint8 oui_type; /* OUI type */ ++ BWL_PRE_PACKED_STRUCT struct { ++ uint8 low; ++ uint8 high; ++ } BWL_POST_PACKED_STRUCT version; /* IE version */ ++} BWL_POST_PACKED_STRUCT wpa_ie_fixed_t; ++#define WPA_IE_OUITYPE_LEN 4 ++#define WPA_IE_FIXED_LEN 8 ++#define WPA_IE_TAG_FIXED_LEN 6 ++ ++typedef BWL_PRE_PACKED_STRUCT struct { ++ uint8 tag; /* TAG */ ++ uint8 length; /* TAG length */ ++ BWL_PRE_PACKED_STRUCT struct { ++ uint8 low; ++ uint8 high; ++ } BWL_POST_PACKED_STRUCT version; /* IE version */ ++} BWL_POST_PACKED_STRUCT wpa_rsn_ie_fixed_t; ++#define WPA_RSN_IE_FIXED_LEN 4 ++#define WPA_RSN_IE_TAG_FIXED_LEN 2 ++typedef uint8 wpa_pmkid_t[WPA2_PMKID_LEN]; ++ ++/* WPA suite/multicast suite */ ++typedef BWL_PRE_PACKED_STRUCT struct ++{ ++ uint8 oui[3]; ++ uint8 type; ++} BWL_POST_PACKED_STRUCT wpa_suite_t, wpa_suite_mcast_t; ++#define WPA_SUITE_LEN 4 ++ ++/* WPA unicast suite list/key management suite list */ ++typedef BWL_PRE_PACKED_STRUCT struct ++{ ++ BWL_PRE_PACKED_STRUCT struct { ++ uint8 low; ++ uint8 high; ++ } BWL_POST_PACKED_STRUCT count; ++ wpa_suite_t list[1]; ++} BWL_POST_PACKED_STRUCT wpa_suite_ucast_t, wpa_suite_auth_key_mgmt_t; ++#define WPA_IE_SUITE_COUNT_LEN 2 ++typedef BWL_PRE_PACKED_STRUCT struct ++{ ++ BWL_PRE_PACKED_STRUCT struct { ++ uint8 low; ++ uint8 high; ++ } BWL_POST_PACKED_STRUCT count; ++ wpa_pmkid_t list[1]; ++} BWL_POST_PACKED_STRUCT wpa_pmkid_list_t; ++ ++/* WPA cipher suites */ ++#define WPA_CIPHER_NONE 0 /* None */ ++#define WPA_CIPHER_WEP_40 1 /* WEP (40-bit) */ ++#define WPA_CIPHER_TKIP 2 /* TKIP: default for WPA */ ++#define WPA_CIPHER_AES_OCB 3 /* AES (OCB) */ ++#define WPA_CIPHER_AES_CCM 4 /* AES (CCM) */ ++#define WPA_CIPHER_WEP_104 5 /* WEP (104-bit) */ ++#define WPA_CIPHER_BIP 6 /* WEP (104-bit) */ ++#define WPA_CIPHER_TPK 7 /* Group addressed traffic not allowed */ ++#ifdef BCMWAPI_WPI ++#define WAPI_CIPHER_NONE WPA_CIPHER_NONE ++#define WAPI_CIPHER_SMS4 11 ++ ++#define WAPI_CSE_WPI_SMS4 1 ++#endif /* BCMWAPI_WPI */ ++ ++ ++#define IS_WPA_CIPHER(cipher) ((cipher) == WPA_CIPHER_NONE || \ ++ (cipher) == WPA_CIPHER_WEP_40 || \ ++ (cipher) == WPA_CIPHER_WEP_104 || \ ++ (cipher) == WPA_CIPHER_TKIP || \ ++ (cipher) == WPA_CIPHER_AES_OCB || \ ++ (cipher) == WPA_CIPHER_AES_CCM || \ ++ (cipher) == WPA_CIPHER_TPK) ++ ++#ifdef BCMWAPI_WAI ++#define IS_WAPI_CIPHER(cipher) ((cipher) == WAPI_CIPHER_NONE || \ ++ (cipher) == WAPI_CSE_WPI_SMS4) ++ ++/* convert WAPI_CSE_WPI_XXX to WAPI_CIPHER_XXX */ ++#define WAPI_CSE_WPI_2_CIPHER(cse) ((cse) == WAPI_CSE_WPI_SMS4 ? \ ++ WAPI_CIPHER_SMS4 : WAPI_CIPHER_NONE) ++ ++#define WAPI_CIPHER_2_CSE_WPI(cipher) ((cipher) == WAPI_CIPHER_SMS4 ? \ ++ WAPI_CSE_WPI_SMS4 : WAPI_CIPHER_NONE) ++#endif /* BCMWAPI_WAI */ ++ ++ ++/* WPA TKIP countermeasures parameters */ ++#define WPA_TKIP_CM_DETECT 60 /* multiple MIC failure window (seconds) */ ++#define WPA_TKIP_CM_BLOCK 60 /* countermeasures active window (seconds) */ ++ ++/* RSN IE defines */ ++#define RSN_CAP_LEN 2 /* Length of RSN capabilities field (2 octets) */ ++ ++/* RSN Capabilities defined in 802.11i */ ++#define RSN_CAP_PREAUTH 0x0001 ++#define RSN_CAP_NOPAIRWISE 0x0002 ++#define RSN_CAP_PTK_REPLAY_CNTR_MASK 0x000C ++#define RSN_CAP_PTK_REPLAY_CNTR_SHIFT 2 ++#define RSN_CAP_GTK_REPLAY_CNTR_MASK 0x0030 ++#define RSN_CAP_GTK_REPLAY_CNTR_SHIFT 4 ++#define RSN_CAP_1_REPLAY_CNTR 0 ++#define RSN_CAP_2_REPLAY_CNTRS 1 ++#define RSN_CAP_4_REPLAY_CNTRS 2 ++#define RSN_CAP_16_REPLAY_CNTRS 3 ++#ifdef MFP ++#define RSN_CAP_MFPR 0x0040 ++#define RSN_CAP_MFPC 0x0080 ++#endif ++ ++/* WPA capabilities defined in 802.11i */ ++#define WPA_CAP_4_REPLAY_CNTRS RSN_CAP_4_REPLAY_CNTRS ++#define WPA_CAP_16_REPLAY_CNTRS RSN_CAP_16_REPLAY_CNTRS ++#define WPA_CAP_REPLAY_CNTR_SHIFT RSN_CAP_PTK_REPLAY_CNTR_SHIFT ++#define WPA_CAP_REPLAY_CNTR_MASK RSN_CAP_PTK_REPLAY_CNTR_MASK ++ ++/* WPA capabilities defined in 802.11zD9.0 */ ++#define WPA_CAP_PEER_KEY_ENABLE (0x1 << 1) /* bit 9 */ ++ ++/* WPA Specific defines */ ++#define WPA_CAP_LEN RSN_CAP_LEN /* Length of RSN capabilities in RSN IE (2 octets) */ ++#define WPA_PMKID_CNT_LEN 2 /* Length of RSN PMKID count (2 octests) */ ++ ++#define WPA_CAP_WPA2_PREAUTH RSN_CAP_PREAUTH ++ ++#ifdef BCMWAPI_WAI ++#define WAPI_CAP_PREAUTH RSN_CAP_PREAUTH ++ ++/* Other WAI definition */ ++#define WAPI_WAI_REQUEST 0x00F1 ++#define WAPI_UNICAST_REKEY 0x00F2 ++#define WAPI_STA_AGING 0x00F3 ++#define WAPI_MUTIL_REKEY 0x00F4 ++#define WAPI_STA_STATS 0x00F5 ++ ++#define WAPI_USK_REKEY_COUNT 0x4000000 /* 0xA00000 */ ++#define WAPI_MSK_REKEY_COUNT 0x4000000 /* 0xA00000 */ ++#endif /* BCMWAPI_WAI */ ++#define WPA2_PMKID_COUNT_LEN 2 ++ ++ ++/* This marks the end of a packed structure section. */ ++#include ++ ++#endif /* _proto_wpa_h_ */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/sbchipc.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/sbchipc.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/sbchipc.h 2014-01-27 01:30:30.101433269 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/sbchipc.h 2014-02-15 00:43:44.793014092 +0100 +@@ -5,9 +5,9 @@ + * JTAG, 0/1/2 UARTs, clock frequency control, a watchdog interrupt timer, + * GPIO interface, extbus, and support for serial and parallel flashes. + * +- * $Id: sbchipc.h 385540 2013-02-15 23:14:50Z $ ++ * $Id: sbchipc.h 347614 2012-07-27 10:24:51Z $ + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -291,10 +291,10 @@ typedef volatile struct { + uint32 pllcontrol_data; + uint32 pmustrapopt; /* 0x668, corerev >= 28 */ + uint32 pmu_xtalfreq; /* 0x66C, pmurev >= 10 */ +- uint32 retention_ctl; /* 0x670 */ ++ uint32 retention_ctl; /* 0x670 */ + uint32 PAD[3]; +- uint32 retention_grpidx; /* 0x680 */ +- uint32 retention_grpctl; /* 0x684 */ ++ uint32 retention_grpidx; /* 0x680 */ ++ uint32 retention_grpctl; /* 0x684 */ + uint32 PAD[94]; + uint16 sromotp[512]; /* 0x800 */ + #ifdef NFLASH_SUPPORT +@@ -362,56 +362,14 @@ typedef volatile struct { + uint32 nand_ctrl_status; + #endif /* NFLASH_SUPPORT */ + uint32 gci_corecaps0; /* GCI starting at 0xC00 */ +- uint32 gci_corecaps1; +- uint32 gci_corecaps2; +- uint32 gci_corectrl; +- uint32 gci_corestat; /* 0xC10 */ +- uint32 gci_intstat; /* 0xC14 */ +- uint32 gci_intmask; /* 0xC18 */ +- uint32 gci_wakemask; /* 0xC1C */ +- uint32 gci_levelintstat; /* 0xC20 */ +- uint32 gci_eventintstat; /* 0xC24 */ +- uint32 PAD[6]; +- uint32 gci_indirect_addr; /* 0xC40 */ +- uint32 gci_gpioctl; /* 0xC44 */ +- uint32 PAD; +- uint32 gci_gpiomask; /* 0xC4C */ +- uint32 PAD; +- uint32 gci_miscctl; /* 0xC54 */ +- uint32 PAD[2]; +- uint32 gci_input[32]; /* C60 */ +- uint32 gci_event[32]; /* CE0 */ +- uint32 gci_output[4]; /* D60 */ +- uint32 gci_control_0; /* 0xD70 */ +- uint32 gci_control_1; /* 0xD74 */ +- uint32 gci_level_polreg; /* 0xD78 */ +- uint32 gci_levelintmask; /* 0xD7C */ +- uint32 gci_eventintmask; /* 0xD80 */ +- uint32 PAD[3]; +- uint32 gci_inbandlevelintmask; /* 0xD90 */ +- uint32 gci_inbandeventintmask; /* 0xD94 */ +- uint32 PAD[2]; +- uint32 gci_seciauxtx; /* 0xDA0 */ +- uint32 gci_seciauxrx; /* 0xDA4 */ +- uint32 gci_secitx_datatag; /* 0xDA8 */ +- uint32 gci_secirx_datatag; /* 0xDAC */ +- uint32 gci_secitx_datamask; /* 0xDB0 */ +- uint32 gci_seciusef0tx_reg; /* 0xDB4 */ +- uint32 gci_secif0tx_offset; /* 0xDB8 */ +- uint32 gci_secif0rx_offset; /* 0xDBC */ +- uint32 gci_secif1tx_offset; /* 0xDC0 */ +- uint32 PAD[3]; +- uint32 gci_uartescval; /* DD0 */ +- uint32 PAD[3]; +- uint32 gci_secibauddiv; /* DE0 */ +- uint32 gci_secifcr; /* DE4 */ +- uint32 gci_secilcr; /* DE8 */ +- uint32 gci_secimcr; /* DEC */ +- uint32 PAD[2]; +- uint32 gci_baudadj; /* DF8 */ +- uint32 PAD; +- uint32 gci_chipctrl; /* 0xE00 */ +- uint32 gci_chipsts; /* 0xE04 */ ++ uint32 gci_corecaps1; ++ uint32 gci_corecaps2; ++ uint32 gci_corectrl; ++ uint32 gci_corestat; /* 0xC10 */ ++ uint32 PAD[11]; ++ uint32 gci_indirect_addr; /* 0xC40 */ ++ uint32 PAD[111]; ++ uint32 gci_chipctrl; /* 0xE00 */ + } chipcregs_t; + + #endif /* _LANGUAGE_ASSEMBLY */ +@@ -517,11 +475,8 @@ typedef volatile struct { + #define CC_CAP2_GSIO 0x00000002 /* GSIO (spi/i2c) present, rev >= 37 */ + + /* capabilities extension */ +-#define CC_CAP_EXT_SECI_PRESENT 0x00000001 /* SECI present */ +-#define CC_CAP_EXT_GCI_PRESENT 0x00000004 /* GCI present */ ++#define CC_CAP_EXT_SECI_PRESENT 0x00000001 /* SECI present */ + +-/* WL Channel Info to BT via GCI - bits 40 - 47 */ +-#define GCI_WL_CHN_INFO_MASK (0xFF00) + /* PLL type */ + #define PLL_NONE 0x00000000 + #define PLL_TYPE1 0x00010000 /* 48MHz base, 3 dividers */ +@@ -538,28 +493,6 @@ typedef volatile struct { + /* ALP clock on pre-PMU chips */ + #define ALP_CLOCK 20000000 + +-#ifdef CFG_SIM +-#define NS_ALP_CLOCK 84922 +-#define NS_SLOW_ALP_CLOCK 84922 +-#define NS_CPU_CLOCK 534500 +-#define NS_SLOW_CPU_CLOCK 534500 +-#define NS_SI_CLOCK 271750 +-#define NS_SLOW_SI_CLOCK 271750 +-#define NS_FAST_MEM_CLOCK 271750 +-#define NS_MEM_CLOCK 271750 +-#define NS_SLOW_MEM_CLOCK 271750 +-#else +-#define NS_ALP_CLOCK 125000000 +-#define NS_SLOW_ALP_CLOCK 100000000 +-#define NS_CPU_CLOCK 1000000000 +-#define NS_SLOW_CPU_CLOCK 800000000 +-#define NS_SI_CLOCK 250000000 +-#define NS_SLOW_SI_CLOCK 200000000 +-#define NS_FAST_MEM_CLOCK 800000000 +-#define NS_MEM_CLOCK 533000000 +-#define NS_SLOW_MEM_CLOCK 400000000 +-#endif /* CFG_SIM */ +- + /* HT clock */ + #define HT_CLOCK 80000000 + +@@ -884,33 +817,6 @@ typedef volatile struct { + #define PCTL_ILP_DIV_EN 0x00000002 + #define PCTL_LPO_SEL 0x00000001 + +-/* Retention Control */ +-#define PMU_RCTL_CLK_DIV_SHIFT 0 +-#define PMU_RCTL_CHAIN_LEN_SHIFT 12 +-#define PMU_RCTL_MACPHY_DISABLE_SHIFT 26 +-#define PMU_RCTL_MACPHY_DISABLE_MASK (1 << 26) +-#define PMU_RCTL_LOGIC_DISABLE_SHIFT 27 +-#define PMU_RCTL_LOGIC_DISABLE_MASK (1 << 27) +-#define PMU_RCTL_MEMSLP_LOG_SHIFT 28 +-#define PMU_RCTL_MEMSLP_LOG_MASK (1 << 28) +-#define PMU_RCTL_MEMRETSLP_LOG_SHIFT 29 +-#define PMU_RCTL_MEMRETSLP_LOG_MASK (1 << 29) +- +-/* Retention Group Control */ +-#define PMU_RCTLGRP_CHAIN_LEN_SHIFT 0 +-#define PMU_RCTLGRP_RMODE_ENABLE_SHIFT 14 +-#define PMU_RCTLGRP_RMODE_ENABLE_MASK (1 << 14) +-#define PMU_RCTLGRP_DFT_ENABLE_SHIFT 15 +-#define PMU_RCTLGRP_DFT_ENABLE_MASK (1 << 15) +-#define PMU_RCTLGRP_NSRST_DISABLE_SHIFT 16 +-#define PMU_RCTLGRP_NSRST_DISABLE_MASK (1 << 16) +-/* Retention Group Control special for 4334 */ +-#define PMU4334_RCTLGRP_CHAIN_LEN_GRP0 338 +-#define PMU4334_RCTLGRP_CHAIN_LEN_GRP1 315 +-/* Retention Group Control special for 43341 */ +-#define PMU43341_RCTLGRP_CHAIN_LEN_GRP0 366 +-#define PMU43341_RCTLGRP_CHAIN_LEN_GRP1 330 +- + /* Fields in clkstretch */ + #define CSTRETCH_HT 0xffff0000 + #define CSTRETCH_ALP 0x0000ffff +@@ -978,8 +884,6 @@ typedef volatile struct { + #define SFLASH_AT 0x200 /* Atmel serial flash */ + #define NFLASH 0x300 + #define PFLASH 0x700 /* Parallel flash */ +-#define QSPIFLASH_ST 0x800 +-#define QSPIFLASH_AT 0x900 + + /* Bits in the ExtBus config registers */ + #define CC_CFG_EN 0x0001 /* Enable */ +@@ -1175,7 +1079,6 @@ typedef volatile struct { + + /* PMU chip control0 register */ + #define PMU_CHIPCTL0 0 +-#define PMU43143_CC0_SDIO_DRSTR_OVR (1 << 31) /* sdio drive strength override enable */ + + /* clock req types */ + #define PMU_CC1_CLKREQ_TYPE_SHIFT 19 +@@ -1209,9 +1112,6 @@ typedef volatile struct { + #define PMU_CC3_ENABLE_RF_SHIFT 22 + #define PMU_CC3_RF_DISABLE_IVALUE_SHIFT 23 + +-/* PMU chip control5 register */ +-#define PMU_CHIPCTL5 5 +- + + /* PMU corerev and chip specific PLL controls. + * PMU_PLL_XX where is PMU corerev and is an arbitrary number +@@ -1600,10 +1500,6 @@ typedef volatile struct { + #define CCTRL43217_EXTPA_C0 (1<<13) /* core0 extPA in ChipControl 1, bit 13 */ + #define CCTRL43217_EXTPA_C1 (1<<8) /* core1 extPA in ChipControl 1, bit 8 */ + +-/* 43228 Chip specific ChipControl register bits */ +-#define CCTRL43228_EXTPA_C0 (1<<14) /* core1 extPA in ChipControl 1, bit 14 */ +-#define CCTRL43228_EXTPA_C1 (1<<9) /* core0 extPA in ChipControl 1, bit 1 */ +- + /* 4328 resources */ + #define RES4328_EXT_SWITCHER_PWM 0 /* 0x00001 */ + #define RES4328_BB_SWITCHER_PWM 1 /* 0x00002 */ +@@ -1847,36 +1743,9 @@ typedef volatile struct { + #define CST43239_CHIPMODE_GSPI(cs) (((cs) & (1 << 0)) == (1 << 0)) /* gSPI */ + + /* 4324 resources */ +-/* 43242 use same PMU as 4324 */ +-#define RES4324_LPLDO_PU 0 +-#define RES4324_RESET_PULLDN_DIS 1 +-#define RES4324_PMU_BG_PU 2 +-#define RES4324_HSIC_LDO_PU 3 +-#define RES4324_CBUCK_LPOM_PU 4 +-#define RES4324_CBUCK_PFM_PU 5 +-#define RES4324_CLDO_PU 6 +-#define RES4324_LPLDO2_LVM 7 +-#define RES4324_LNLDO1_PU 8 +-#define RES4324_LNLDO2_PU 9 +-#define RES4324_LDO3P3_PU 10 +-#define RES4324_OTP_PU 11 +-#define RES4324_XTAL_PU 12 +-#define RES4324_BBPLL_PU 13 +-#define RES4324_LQ_AVAIL 14 +-#define RES4324_WL_CORE_READY 17 +-#define RES4324_ILP_REQ 18 +-#define RES4324_ALP_AVAIL 19 +-#define RES4324_PALDO_PU 20 +-#define RES4324_RADIO_PU 21 +-#define RES4324_SR_CLK_STABLE 22 +-#define RES4324_SR_SAVE_RESTORE 23 +-#define RES4324_SR_PHY_PWRSW 24 +-#define RES4324_SR_PHY_PIC 25 +-#define RES4324_SR_SUBCORE_PWRSW 26 +-#define RES4324_SR_SUBCORE_PIC 27 +-#define RES4324_SR_MEM_PM0 28 ++#define RES4324_OTP_PU 10 + #define RES4324_HT_AVAIL 29 +-#define RES4324_MACPHY_CLKAVAIL 30 ++#define RES4324_MACPHY_CLKAVAIL 30 + + /* 4324 Chip specific ChipStatus register bits */ + #define CST4324_SPROM_MASK 0x00000080 +@@ -1887,9 +1756,6 @@ typedef volatile struct { + #define CST4324_CHIPMODE_SDIOD(cs) ((~(cs)) & (1 << 2)) /* SDIO || gSPI */ + #define CST4324_CHIPMODE_USB20D(cs) (((cs) & CST4324_CHIPMODE_MASK) == 0x6) /* USB || USBDA */ + +-/* 43242 Chip specific ChipStatus register bits */ +-#define CST43242_SFLASH_MASK 0x00000008 +- + /* 4331 resources */ + #define RES4331_REGULATOR 0 + #define RES4331_ILP_REQUEST 1 +@@ -2125,42 +1991,6 @@ typedef volatile struct { + #define PMU_VREG0_DISABLE_PULLD_BT_SHIFT 2 + #define PMU_VREG0_DISABLE_PULLD_WL_SHIFT 3 + +-#define PMU_VREG4_ADDR 4 +- +-#define PMU_VREG4_CLDO_PWM_SHIFT 4 +-#define PMU_VREG4_CLDO_PWM_MASK 0x7 +- +-#define PMU_VREG4_LPLDO1_SHIFT 15 +-#define PMU_VREG4_LPLDO1_MASK 0x7 +-#define PMU_VREG4_LPLDO1_1p20V 0 +-#define PMU_VREG4_LPLDO1_1p15V 1 +-#define PMU_VREG4_LPLDO1_1p10V 2 +-#define PMU_VREG4_LPLDO1_1p25V 3 +-#define PMU_VREG4_LPLDO1_1p05V 4 +-#define PMU_VREG4_LPLDO1_1p00V 5 +-#define PMU_VREG4_LPLDO1_0p95V 6 +-#define PMU_VREG4_LPLDO1_0p90V 7 +- +-#define PMU_VREG4_LPLDO2_LVM_SHIFT 18 +-#define PMU_VREG4_LPLDO2_LVM_MASK 0x7 +-#define PMU_VREG4_LPLDO2_HVM_SHIFT 21 +-#define PMU_VREG4_LPLDO2_HVM_MASK 0x7 +-#define PMU_VREG4_LPLDO2_LVM_HVM_MASK 0x3f +-#define PMU_VREG4_LPLDO2_1p00V 0 +-#define PMU_VREG4_LPLDO2_1p15V 1 +-#define PMU_VREG4_LPLDO2_1p20V 2 +-#define PMU_VREG4_LPLDO2_1p10V 3 +-#define PMU_VREG4_LPLDO2_0p90V 4 /* 4 - 7 is 0.90V */ +- +-#define PMU_VREG4_HSICLDO_BYPASS_SHIFT 27 +-#define PMU_VREG4_HSICLDO_BYPASS_MASK 0x1 +- +-#define PMU_VREG5_ADDR 5 +-#define PMU_VREG5_HSICAVDD_PD_SHIFT 6 +-#define PMU_VREG5_HSICAVDD_PD_MASK 0x1 +-#define PMU_VREG5_HSICDVDD_PD_SHIFT 11 +-#define PMU_VREG5_HSICDVDD_PD_MASK 0x1 +- + /* 4334 resources */ + #define RES4334_LPLDO_PU 0 + #define RES4334_RESET_PULLDN_DIS 1 +@@ -2216,78 +2046,12 @@ typedef volatile struct { + #define PCTL_4334_GPIO3_ENAB (1 << 3) + + /* 4334 Chip control */ +-#define CCTRL4334_PMU_WAKEUP_GPIO1 (1 << 0) +-#define CCTRL4334_PMU_WAKEUP_HSIC (1 << 1) +-#define CCTRL4334_PMU_WAKEUP_AOS (1 << 2) +-#define CCTRL4334_HSIC_WAKE_MODE (1 << 3) +-#define CCTRL4334_HSIC_INBAND_GPIO1 (1 << 4) + #define CCTRL4334_HSIC_LDO_PU (1 << 23) + +-/* 4334 Chip control 3 */ +-#define CCTRL4334_BLOCK_EXTRNL_WAKE (1 << 4) +-#define CCTRL4334_SAVERESTORE_FIX (1 << 5) +- +-/* 43341 Chip control 3 */ +-#define CCTRL43341_BLOCK_EXTRNL_WAKE (1 << 13) +-#define CCTRL43341_SAVERESTORE_FIX (1 << 14) +-#define CCTRL43341_BT_ISO_SEL (1 << 16) +- +-/* 4334 Chip specific ChipControl1 register bits */ +-#define CCTRL1_4334_GPIO_SEL (1 << 0) /* 1=select GPIOs to be muxed out */ +-#define CCTRL1_4334_ERCX_SEL (1 << 1) /* 1=select ERCX BT coex to be muxed out */ +-#define CCTRL1_4334_SDIO_HOST_WAKE (1 << 2) /* SDIO: 1=configure GPIO0 for host wake */ +-#define CCTRL1_4334_JTAG_DISABLE (1 << 3) /* 1=disable JTAG interface on mux'd pins */ +-#define CCTRL1_4334_UART_ON_4_5 (1 << 28) /* 1=UART_TX/UART_RX muxed on GPIO_4/5 (4334B0/1) */ +- + /* 4324 Chip specific ChipControl1 register bits */ + #define CCTRL1_4324_GPIO_SEL (1 << 0) /* 1=select GPIOs to be muxed out */ + #define CCTRL1_4324_SDIO_HOST_WAKE (1 << 2) /* SDIO: 1=configure GPIO0 for host wake */ + +-/* 43143 chip-specific ChipStatus register bits based on Confluence documentation */ +-/* register contains strap values sampled during POR */ +-#define CST43143_REMAP_TO_ROM (3 << 0) /* 00=Boot SRAM, 01=Boot ROM, 10=Boot SFLASH */ +-#define CST43143_SDIO_EN (1 << 2) /* 0 = USB Enab, SDIO pins are GPIO or I2S */ +-#define CST43143_SDIO_ISO (1 << 3) /* 1 = SDIO isolated */ +-#define CST43143_USB_CPU_LESS (1 << 4) /* 1 = CPULess mode Enabled */ +-#define CST43143_CBUCK_MODE (3 << 6) /* Indicates what controller mode CBUCK is in */ +-#define CST43143_POK_CBUCK (1 << 8) /* 1 = 1.2V CBUCK voltage ready */ +-#define CST43143_PMU_OVRSPIKE (1 << 9) +-#define CST43143_PMU_OVRTEMP (0xF << 10) +-#define CST43143_SR_FLL_CAL_DONE (1 << 14) +-#define CST43143_USB_PLL_LOCKDET (1 << 15) +-#define CST43143_PMU_PLL_LOCKDET (1 << 16) +-#define CST43143_CHIPMODE_SDIOD(cs) (((cs) & CST43143_SDIO_EN) != 0) /* SDIO */ +- +-/* 43143 Chip specific ChipControl register bits */ +-/* 00: SECI is disabled (JATG functional), 01: 2 wire, 10: 4 wire */ +-#define CCTRL_43143_SECI (1<<0) +-#define CCTRL_43143_BT_LEGACY (1<<1) +-#define CCTRL_43143_I2S_MODE (1<<2) /* 0: SDIO enabled */ +-#define CCTRL_43143_I2S_MASTER (1<<3) /* 0: I2S MCLK input disabled */ +-#define CCTRL_43143_I2S_FULL (1<<4) /* 0: I2S SDIN and SPDIF_TX inputs disabled */ +-#define CCTRL_43143_GSIO (1<<5) /* 0: sFlash enabled */ +-#define CCTRL_43143_RF_SWCTRL_MASK (7<<6) /* 0: disabled */ +-#define CCTRL_43143_RF_SWCTRL_0 (1<<6) +-#define CCTRL_43143_RF_SWCTRL_1 (2<<6) +-#define CCTRL_43143_RF_SWCTRL_2 (4<<6) +-#define CCTRL_43143_RF_XSWCTRL (1<<9) /* 0: UART enabled */ +-#define CCTRL_43143_HOST_WAKE0 (1<<11) /* 1: SDIO separate interrupt output from GPIO4 */ +-#define CCTRL_43143_HOST_WAKE1 (1<<12) /* 1: SDIO separate interrupt output from GPIO16 */ +- +-/* 43143 resources, based on pmu_params.xls V1.19 */ +-#define RES43143_EXT_SWITCHER_PWM 0 /* 0x00001 */ +-#define RES43143_XTAL_PU 1 /* 0x00002 */ +-#define RES43143_ILP_REQUEST 2 /* 0x00004 */ +-#define RES43143_ALP_AVAIL 3 /* 0x00008 */ +-#define RES43143_WL_CORE_READY 4 /* 0x00010 */ +-#define RES43143_BBPLL_PWRSW_PU 5 /* 0x00020 */ +-#define RES43143_HT_AVAIL 6 /* 0x00040 */ +-#define RES43143_RADIO_PU 7 /* 0x00080 */ +-#define RES43143_MACPHY_CLK_AVAIL 8 /* 0x00100 */ +-#define RES43143_OTP_PU 9 /* 0x00200 */ +-#define RES43143_LQ_AVAIL 10 /* 0x00400 */ +- +-#define PMU43143_XTAL_CORE_SIZE_MASK 0x3F + + /* 4313 resources */ + #define RES4313_BB_PU_RSRC 0 +@@ -2390,19 +2154,11 @@ typedef volatile struct { + #define FLSTRCF4706_1ST_MADDR_SEG_256MB 0x00000070 /* 256MB */ + + /* 4360 Chip specific ChipControl register bits */ +-#define CCTRL4360_I2C_MODE (1 << 0) +-#define CCTRL4360_UART_MODE (1 << 1) + #define CCTRL4360_SECI_MODE (1 << 2) + #define CCTRL4360_BTSWCTRL_MODE (1 << 3) +-#define CCTRL4360_DISCRETE_FEMCTRL_MODE (1 << 4) +-#define CCTRL4360_DIGITAL_PACTRL_MODE (1 << 5) +-#define CCTRL4360_BTSWCTRL_AND_DIGPA_PRESENT (1 << 6) +-#define CCTRL4360_EXTRA_GPIO_MODE (1 << 7) + #define CCTRL4360_EXTRA_FEMCTRL_MODE (1 << 8) + #define CCTRL4360_BT_LGCY_MODE (1 << 9) + #define CCTRL4360_CORE2FEMCTRL4_ON (1 << 21) +-#define CCTRL4360_SECI_ON_GPIO01 (1 << 24) +- + + /* 4360 PMU resources and chip status bits */ + #define RES4360_REGULATOR 0 +@@ -2433,13 +2189,6 @@ typedef volatile struct { + + #define CCTRL_4360_UART_SEL 0x2 + +-/* defines to detect active host interface in use */ +-#define CHIP_HOSTIF_PCIEMODE 0x1 +-#define CHIP_HOSTIF_USBMODE 0x2 +-#define CHIP_HOSTIF_SDIOMODE 0x4 +-#define CHIP_HOSTIF_PCIE(sih) (si_chip_hostif(sih) == CHIP_HOSTIF_PCIEMODE) +-#define CHIP_HOSTIF_SDIO(sih) (si_chip_hostif(sih) == CHIP_HOSTIF_SDIOMODE) +- + /* 4335 resources */ + #define RES4335_LPLDO_PO 0 + #define RES4335_PMU_BG_PU 1 +@@ -2488,226 +2237,10 @@ typedef volatile struct { + #define CCTRL1_4335_GPIO_SEL (1 << 0) /* 1=select GPIOs to be muxed out */ + #define CCTRL1_4335_SDIO_HOST_WAKE (1 << 2) /* SDIO: 1=configure GPIO0 for host wake */ + +-#define CR4_4335_RAM_BASE (0x180000) +-#define PATCHTBL_SIZE (0x800) +-#define CR4_4350_RAM_BASE (0x180000) +-#define CR4_4360_RAM_BASE (0x0) +- +- +-/* 4335 chip OTP present & OTP select bits. */ +-#define SPROM4335_OTP_SELECT 0x00000010 +-#define SPROM4335_OTP_PRESENT 0x00000020 +- +-/* 4335 GCI specific bits. */ +-#define CC4335_GCI_STRAP_OVERRIDE_SFLASH_PRESENT (1 << 24) +-#define CC4335_GCI_STRAP_OVERRIDE_SFLASH_TYPE 25 +-#define CC4335_GCI_FUNC_SEL_PAD_SDIO 0x00707770 +- +-/* SFLASH clkdev specific bits. */ +-#define CC4335_SFLASH_CLKDIV_MASK 0x1F000000 +-#define CC4335_SFLASH_CLKDIV_SHIFT 25 +- +-/* 4335 OTP bits for SFLASH. */ +-#define CC4335_SROM_OTP_SFLASH 40 +-#define CC4335_SROM_OTP_SFLASH_PRESENT 0x1 +-#define CC4335_SROM_OTP_SFLASH_TYPE 0x2 +-#define CC4335_SROM_OTP_SFLASH_CLKDIV_MASK 0x003C +-#define CC4335_SROM_OTP_SFLASH_CLKDIV_SHIFT 2 +- +-/* 4335 resources--END */ + ++#define CR4_RAM_BASE (0x180000) + +-/* 4350 Chipcommon ChipStatus bits */ +-#define CST4350_SDIO_MODE 0x00000001 +-#define CST4350_HSIC20D_MODE 0x00000002 +-#define CST4350_BP_ON_HSIC_CLK 0x00000004 +-#define CST4350_PCIE_MODE 0x00000008 +-#define CST4350_USB20D_MODE 0x00000010 +-#define CST4350_USB30D_MODE 0x00000020 +-#define CST4350_SPROM_PRESENT 0x00000040 +-#define CST4350_RSRC_INIT_MODE_0 0x00000080 +-#define CST4350_RSRC_INIT_MODE_1 0x00000100 +-#define CST4350_SEL0_SDIO 0x00000200 +-#define CST4350_SEL1_SDIO 0x00000400 +-#define CST4350_SDIO_PAD_MODE 0x00000800 +-#define CST4350_BBPLL_LOCKED 0x00001000 +-#define CST4350_USBPLL_LOCKED 0x00002000 +-#define CST4350_LINE_STATE 0x0000C000 +-#define CST4350_SERDES_PIPE_PLLLOCK 0x00010000 +-#define CST4350_BT_READY 0x00020000 +-#define CST4350_SFLASH_PRESENT 0x00040000 +-#define CST4350_CPULESS_ENABLE 0x00080000 +-#define CST4350_STRAP_HOST_IFC_1 0x00100000 +-#define CST4350_STRAP_HOST_IFC_2 0x00200000 +-#define CST4350_STRAP_HOST_IFC_3 0x00400000 +-#define CST4350_RAW_SPROM_PRESENT 0x00800000 +-#define CST4350_APP_CLK_SWITCH_SEL_RDBACK 0x01000000 +-#define CST4350_RAW_RSRC_INIT_MODE_0 0x02000000 +-#define CST4350_SDIO_PAD_VDDIO 0x04000000 +-#define CST4350_GSPI_MODE 0x08000000 +-#define CST4350_PACKAGE_OPTION 0xF0000000 +- +-/* strap_host_ifc strap value */ +-#define CST4350_HOST_IFC_MASK 0x00700000 +-#define CST4350_HOST_IFC_SHIFT 20 +- +-/* host_ifc raw mode */ +-#define CST4350_IFC_MODE_SDIOD 0x0 +-#define CST4350_IFC_MODE_HSIC20D 0x1 +-#define CST4350_IFC_MODE_HSIC30D 0x2 +-#define CST4350_IFC_MODE_PCIE 0x3 +-#define CST4350_IFC_MODE_USB20D 0x4 +-#define CST4350_IFC_MODE_USB30D 0x5 +-#define CST4350_IFC_MODE_USB30D_WL 0x6 +-#define CST4350_IFC_MODE_USB30D_BT 0x7 +- +-#define CST4350_IFC_MODE(cs) ((cs & CST4350_HOST_IFC_MASK) >> CST4350_HOST_IFC_SHIFT) +- +-#define CST4350_CHIPMODE_SDIOD(cs) (CST4350_IFC_MODE(cs) == (CST4350_IFC_MODE_SDIOD)) +-#define CST4350_CHIPMODE_USB20D(cs) ((CST4350_IFC_MODE(cs)) == (CST4350_IFC_MODE_USB20D)) +-#define CST4350_CHIPMODE_HSIC20D(cs) (CST4350_IFC_MODE(cs) == (CST4350_IFC_MODE_HSIC20D)) +-#define CST4350_CHIPMODE_HSIC30D(cs) (CST4350_IFC_MODE(cs) == (CST4350_IFC_MODE_HSIC30D)) +-#define CST4350_CHIPMODE_USB30D(cs) (CST4350_IFC_MODE(cs) == (CST4350_IFC_MODE_USB30D)) +-#define CST4350_CHIPMODE_USB30D_WL(cs) (CST4350_IFC_MODE(cs) == (CST4350_IFC_MODE_USB30D_WL)) +-#define CST4350_CHIPMODE_PCIE(cs) (CST4350_IFC_MODE(cs) == (CST4350_IFC_MODE_PCIE)) +- +-/* 4350 PMU resources */ +-#define RES4350_LPLDO_PU 0 +-#define RES4350_PMU_BG_PU 1 +-#define RES4350_PMU_SLEEP 2 +-#define RES4350_RSVD_3 3 +-#define RES4350_CBUCK_LPOM_PU 4 +-#define RES4350_CBUCK_PFM_PU 5 +-#define RES4350_COLD_START_WAIT 6 +-#define RES4350_RSVD_7 7 +-#define RES4350_LNLDO_PU 8 +-#define RES4350_XTALLDO_PU 9 +-#define RES4350_LDO3P3_PU 10 +-#define RES4350_OTP_PU 11 +-#define RES4350_XTAL_PU 12 +-#define RES4350_SR_CLK_START 13 +-#define RES4350_LQ_AVAIL 14 +-#define RES4350_LQ_START 15 +-#define RES4350_RSVD_16 16 +-#define RES4350_WL_CORE_RDY 17 +-#define RES4350_ILP_REQ 18 +-#define RES4350_ALP_AVAIL 19 +-#define RES4350_MINI_PMU 20 +-#define RES4350_RADIO_PU 21 +-#define RES4350_SR_CLK_STABLE 22 +-#define RES4350_SR_SAVE_RESTORE 23 +-#define RES4350_SR_PHY_PWRSW 24 +-#define RES4350_SR_VDDM_PWRSW 25 +-#define RES4350_SR_SUBCORE_PWRSW 26 +-#define RES4350_SR_SLEEP 27 +-#define RES4350_HT_START 28 +-#define RES4350_HT_AVAIL 29 +-#define RES4350_MACPHY_CLKAVAIL 30 +- +-#define MUXENAB4350_UART_MASK (0x0000000f) +- +-/* 4350 GCI function sel values */ +-#define CC4350_FNSEL_HWDEF (0) +-#define CC4350_FNSEL_SAMEASPIN (1) +-#define CC4350_FNSEL_UART (2) +-#define CC4350_FNSEL_SFLASH (3) +-#define CC4350_FNSEL_SPROM (4) +-#define CC4350_FNSEL_I2C (5) +-#define CC4350_FNSEL_MISC0 (6) +-#define CC4350_FNSEL_GCI (7) +-#define CC4350_FNSEL_MISC1 (8) +-#define CC4350_FNSEL_MISC2 (9) +-#define CC4350_FNSEL_PWDOG (10) +-#define CC4350_FNSEL_IND (12) +-#define CC4350_FNSEL_PDN (13) +-#define CC4350_FNSEL_PUP (14) +-#define CC4350_FNSEL_TRISTATE (15) +- +-/* 4350 GPIO */ +-#define CC4350_PIN_GPIO_00 (0) +-#define CC4350_PIN_GPIO_01 (1) +-#define CC4350_PIN_GPIO_02 (2) +-#define CC4350_PIN_GPIO_03 (3) +-#define CC4350_PIN_GPIO_04 (4) +-#define CC4350_PIN_GPIO_05 (5) +-#define CC4350_PIN_GPIO_06 (6) +-#define CC4350_PIN_GPIO_07 (7) +-#define CC4350_PIN_GPIO_08 (8) +-#define CC4350_PIN_GPIO_09 (9) +-#define CC4350_PIN_GPIO_10 (10) +-#define CC4350_PIN_GPIO_11 (11) +-#define CC4350_PIN_GPIO_12 (12) +-#define CC4350_PIN_GPIO_13 (13) +-#define CC4350_PIN_GPIO_14 (14) +-#define CC4350_PIN_GPIO_15 (15) +- +-#define CC2_4350_MEMLPLDO_PWRSW_EN_MASK (1 << 21) +-#define CC2_4350_MEMLPLDO_PWRSW_EN_SHIFT (21) +-#define CC2_4350_SDIO_AOS_WAKEUP_MASK (1 << 24) +-#define CC2_4350_SDIO_AOS_WAKEUP_SHIFT (24) +- +-/* Applies to 4335/4350/4345 */ +-#define CC3_SR_CLK_SR_MEM_MASK (1 << 0) +-#define CC3_SR_CLK_SR_MEM_SHIFT (0) +-#define CC3_SR_BIT1_TBD_MASK (1 << 1) +-#define CC3_SR_BIT1_TBD_SHIFT (1) +-#define CC3_SR_ENGINE_ENABLE_MASK (1 << 2) +-#define CC3_SR_ENGINE_ENABLE_SHIFT (2) +-#define CC3_SR_BIT3_TBD_MASK (1 << 3) +-#define CC3_SR_BIT3_TBD_SHIFT (3) +-#define CC3_SR_MINDIV_FAST_CLK_MASK (0xF << 4) +-#define CC3_SR_MINDIV_FAST_CLK_SHIFT (4) +-#define CC3_SR_R23_SR2_RISE_EDGE_TRIG_MASK (1 << 8) +-#define CC3_SR_R23_SR2_RISE_EDGE_TRIG_SHIFT (8) +-#define CC3_SR_R23_SR2_FALL_EDGE_TRIG_MASK (1 << 9) +-#define CC3_SR_R23_SR2_FALL_EDGE_TRIG_SHIFT (9) +-#define CC3_SR_R23_SR_RISE_EDGE_TRIG_MASK (1 << 10) +-#define CC3_SR_R23_SR_RISE_EDGE_TRIG_SHIFT (10) +-#define CC3_SR_R23_SR_FALL_EDGE_TRIG_MASK (1 << 11) +-#define CC3_SR_R23_SR_FALL_EDGE_TRIG_SHIFT (11) +-#define CC3_SR_NUM_CLK_HIGH_MASK (0x7 << 12) +-#define CC3_SR_NUM_CLK_HIGH_SHIFT (12) +-#define CC3_SR_BIT15_TBD_MASK (1 << 15) +-#define CC3_SR_BIT15_TBD_SHIFT (15) +-#define CC3_SR_PHY_FUNC_PIC_MASK (1 << 16) +-#define CC3_SR_PHY_FUNC_PIC_SHIFT (16) +-#define CC3_SR_BIT17_19_TBD_MASK (0x7 << 17) +-#define CC3_SR_BIT17_19_TBD_SHIFT (17) +-#define CC3_SR_CHIP_TRIGGER_1_MASK (1 << 20) +-#define CC3_SR_CHIP_TRIGGER_1_SHIFT (20) +-#define CC3_SR_CHIP_TRIGGER_2_MASK (1 << 21) +-#define CC3_SR_CHIP_TRIGGER_2_SHIFT (21) +-#define CC3_SR_CHIP_TRIGGER_3_MASK (1 << 22) +-#define CC3_SR_CHIP_TRIGGER_3_SHIFT (22) +-#define CC3_SR_CHIP_TRIGGER_4_MASK (1 << 23) +-#define CC3_SR_CHIP_TRIGGER_4_SHIFT (23) +-#define CC3_SR_ALLOW_SBC_FUNC_PIC_MASK (1 << 24) +-#define CC3_SR_ALLOW_SBC_FUNC_PIC_SHIFT (24) +-#define CC3_SR_BIT25_26_TBD_MASK (0x3 << 25) +-#define CC3_SR_BIT25_26_TBD_SHIFT (25) +-#define CC3_SR_ALLOW_SBC_STBY_MASK (1 << 27) +-#define CC3_SR_ALLOW_SBC_STBY_SHIFT (27) +-#define CC3_SR_GPIO_MUX_MASK (0xF << 28) +-#define CC3_SR_GPIO_MUX_SHIFT (28) +- +-/* Applies to 4335/4350/4345 */ +-#define CC4_SR_INIT_ADDR_MASK (0x3FF0000) +-#define CC4_4350_SR_ASM_ADDR (0x30) +-#define CC4_4335_SR_ASM_ADDR (0x48) +-#define CC4_SR_INIT_ADDR_SHIFT (16) +- +-#define CC4_4350_EN_SR_CLK_ALP_MASK (1 << 30) +-#define CC4_4350_EN_SR_CLK_ALP_SHIFT (30) +-#define CC4_4350_EN_SR_CLK_HT_MASK (1 << 31) +-#define CC4_4350_EN_SR_CLK_HT_SHIFT (31) +- +-#define VREG4_4350_MEMLPDO_PU_MASK (1 << 31) +-#define VREG4_4350_MEMLPDO_PU_SHIFT 31 +- +-#define CC6_4350_PCIE_CLKREQ_WAKEUP_MASK (1 << 4) +-#define CC6_4350_PCIE_CLKREQ_WAKEUP_SHIFT (4) +-#define CC6_4350_PMU_WAKEUP_ALPAVAIL_MASK (1 << 6) +-#define CC6_4350_PMU_WAKEUP_ALPAVAIL_SHIFT (6) ++/* 4335 resources--END */ + + /* GCI chipcontrol register indices */ + #define CC_GCI_CHIPCTRL_00 (0) +@@ -2720,9 +2253,6 @@ typedef volatile struct { + #define CC_GCI_CHIPCTRL_07 (7) + #define CC_GCI_CHIPCTRL_08 (8) + +-#define CC_GCI_06_JTAG_SEL_SHIFT 4 +-#define CC_GCI_06_JTAG_SEL_MASK (1 << 4) +- + #define CC_GCI_NUMCHIPCTRLREGS(cap1) ((cap1 & 0xF00) >> 8) + + /* 4335 pins +@@ -2791,11 +2321,6 @@ typedef volatile struct { + */ + #define MUXENAB4335_UART_MASK (0x0000000f) + +-#define MUXENAB4335_UART_SHIFT 0 +-#define MUXENAB4335_HOSTWAKE_MASK (0x000000f0) /* configure GPIO for SDIO host_wake */ +-#define MUXENAB4335_HOSTWAKE_SHIFT 4 +-#define MUXENAB4335_GETIX(val, name) \ +- ((((val) & MUXENAB4335_ ## name ## _MASK) >> MUXENAB4335_ ## name ## _SHIFT) - 1) + + /* defines to detect active host interface in use */ + #define CHIP_HOSTIF_USB(sih) (si_chip_hostif(sih) & CST4360_MODE_USB) +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/sbconfig.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/sbconfig.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/sbconfig.h 2014-01-27 01:30:30.101433269 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/sbconfig.h 2014-02-15 00:43:44.793014092 +0100 +@@ -1,7 +1,7 @@ + /* + * Broadcom SiliconBackplane hardware register definitions. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/sbhnddma.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/sbhnddma.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/sbhnddma.h 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/sbhnddma.h 2014-02-15 00:43:44.794014114 +0100 +@@ -2,7 +2,7 @@ + * Generic Broadcom Home Networking Division (HND) DMA engine HW interface + * This supports the following chips: BCM42xx, 44xx, 47xx . + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -22,7 +22,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: sbhnddma.h 373617 2012-12-07 23:03:08Z $ ++ * $Id: sbhnddma.h 309193 2012-01-19 00:03:57Z $ + */ + + #ifndef _sbhnddma_h_ +@@ -247,33 +247,10 @@ typedef volatile struct { + */ + #define D64RINGALIGN_BITS 13 + #define D64MAXRINGSZ (1 << D64RINGALIGN_BITS) +-#define D64RINGBOUNDARY (1 << D64RINGALIGN_BITS) ++#define D64RINGALIGN (1 << D64RINGALIGN_BITS) + + #define D64MAXDD (D64MAXRINGSZ / sizeof (dma64dd_t)) + +-/* for cores with large descriptor ring support, descriptor ring size can be up to 4096 */ +-#define D64MAXDD_LARGE ((1 << 16) / sizeof (dma64dd_t)) +- +-/* for cores with large descriptor ring support (4k descriptors), descriptor ring cannot cross +- * 64K boundary +- */ +-#define D64RINGBOUNDARY_LARGE (1 << 16) +- +-/* +- * Default DMA Burstlen values for USBRev >= 12 and SDIORev >= 11. +- * When this field contains the value N, the burst length is 2**(N + 4) bytes. +- */ +-#define D64_DEF_USBBURSTLEN 2 +-#define D64_DEF_SDIOBURSTLEN 1 +- +- +-#ifndef D64_USBBURSTLEN +-#define D64_USBBURSTLEN DMA_BL_64 +-#endif +-#ifndef D64_SDIOBURSTLEN +-#define D64_SDIOBURSTLEN DMA_BL_32 +-#endif +- + /* transmit channel control */ + #define D64_XC_XE 0x00000001 /* transmit enable */ + #define D64_XC_SE 0x00000002 /* transmit suspend request */ +@@ -295,7 +272,7 @@ typedef volatile struct { + #define D64_XP_LD_MASK 0x00001fff /* last valid descriptor */ + + /* transmit channel status */ +-#define D64_XS0_CD_MASK (di->d64_xs0_cd_mask) /* current descriptor pointer */ ++#define D64_XS0_CD_MASK 0x00001fff /* current descriptor pointer */ + #define D64_XS0_XS_MASK 0xf0000000 /* transmit state */ + #define D64_XS0_XS_SHIFT 28 + #define D64_XS0_XS_DISABLED 0x00000000 /* disabled */ +@@ -304,7 +281,7 @@ typedef volatile struct { + #define D64_XS0_XS_STOPPED 0x30000000 /* stopped */ + #define D64_XS0_XS_SUSP 0x40000000 /* suspend pending */ + +-#define D64_XS1_AD_MASK (di->d64_xs1_ad_mask) /* active descriptor */ ++#define D64_XS1_AD_MASK 0x00001fff /* active descriptor */ + #define D64_XS1_XE_MASK 0xf0000000 /* transmit errors */ + #define D64_XS1_XE_SHIFT 28 + #define D64_XS1_XE_NOERR 0x00000000 /* no error */ +@@ -322,7 +299,6 @@ typedef volatile struct { + #define D64_RC_SH 0x00000200 /* separate rx header descriptor enable */ + #define D64_RC_OC 0x00000400 /* overflow continue */ + #define D64_RC_PD 0x00000800 /* parity check disable */ +-#define D64_RC_GE 0x00004000 /* Glom enable */ + #define D64_RC_AE 0x00030000 /* address extension bits */ + #define D64_RC_AE_SHIFT 16 + #define D64_RC_BL_MASK 0x001C0000 /* BurstLen bits */ +@@ -344,7 +320,7 @@ typedef volatile struct { + #define D64_RP_LD_MASK 0x00001fff /* last valid descriptor */ + + /* receive channel status */ +-#define D64_RS0_CD_MASK (di->d64_rs0_cd_mask) /* current descriptor pointer */ ++#define D64_RS0_CD_MASK 0x00001fff /* current descriptor pointer */ + #define D64_RS0_RS_MASK 0xf0000000 /* receive state */ + #define D64_RS0_RS_SHIFT 28 + #define D64_RS0_RS_DISABLED 0x00000000 /* disabled */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/sbpcmcia.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/sbpcmcia.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/sbpcmcia.h 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/sbpcmcia.h 2014-02-15 00:43:44.794014114 +0100 +@@ -1,7 +1,7 @@ + /* + * BCM43XX Sonics SiliconBackplane PCMCIA core hardware definitions. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -21,7 +21,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: sbpcmcia.h 381094 2013-01-25 04:45:06Z $ ++ * $Id: sbpcmcia.h 326494 2012-04-09 13:29:57Z $ + */ + + #ifndef _SBPCMCIA_H +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/sbsdio.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/sbsdio.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/sbsdio.h 2014-01-27 01:30:30.101433269 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/sbsdio.h 2014-02-15 00:43:44.793014092 +0100 +@@ -4,7 +4,7 @@ + * + * SDIO core support 1bit, 4 bit SDIO mode as well as SPI mode. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -24,7 +24,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: sbsdio.h 383835 2013-02-07 23:32:39Z $ ++ * $Id: sbsdio.h 361940 2012-10-10 08:32:12Z $ + */ + + #ifndef _SBSDIO_H +@@ -101,7 +101,6 @@ + * => busy signal is asserted between data blocks. + */ + #define SBSDIO_MESBUSYCTRL_MASK 0x7f +-#define SBSDIO_MESBUSYCTRL_ENAB 0x80 /* Enable busy capability for MES access */ + + /* SBSDIO_DEVICE_CTL */ + #define SBSDIO_DEVCTL_SETBUSY 0x01 /* 1: device will assert busy signal when +@@ -117,9 +116,12 @@ + * external pads in tri-state; requires + * sdio bus power cycle to clear (rev 9) + */ ++#define SBSDIO_DEVCTL_SB_RST_CTL 0x30 /* Force SD->SB reset mapping (rev 11) */ ++#define SBSDIO_DEVCTL_RST_CORECTL 0x00 /* Determined by CoreControl bit */ ++#define SBSDIO_DEVCTL_RST_BPRESET 0x10 /* Force backplane reset */ ++#define SBSDIO_DEVCTL_RST_NOBPRESET 0x20 /* Force no backplane reset */ + #define SBSDIO_DEVCTL_EN_F2_BLK_WATERMARK 0x10 /* Enable function 2 tx for each block */ +-#define SBSDIO_DEVCTL_F2WM_ENAB 0x10 /* Enable F2 Watermark */ +-#define SBSDIO_DEVCTL_NONDAT_PADS_ISO 0x20 /* Isolate sdio clk and cmd (non-data) */ ++ + + /* SBSDIO_FUNC1_CHIPCLKCSR */ + #define SBSDIO_FORCE_ALP 0x01 /* Force ALP request to backplane */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/sbsdpcmdev.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/sbsdpcmdev.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/sbsdpcmdev.h 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/sbsdpcmdev.h 2014-02-15 00:43:44.794014114 +0100 +@@ -2,7 +2,7 @@ + * Broadcom SiliconBackplane SDIO/PCMCIA hardware-specific + * device core support + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -22,7 +22,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: sbsdpcmdev.h 336848 2012-06-05 11:28:07Z $ ++ * $Id: sbsdpcmdev.h 347614 2012-07-27 10:24:51Z $ + */ + + #ifndef _sbsdpcmdev_h_ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/sbsocram.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/sbsocram.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/sbsocram.h 2014-01-27 01:30:30.101433269 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/sbsocram.h 2014-02-15 00:43:44.793014092 +0100 +@@ -1,7 +1,7 @@ + /* + * BCM47XX Sonics SiliconBackplane embedded ram core + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/sdio.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/sdio.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/sdio.h 2014-01-27 01:30:30.101433269 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/sdio.h 2014-02-15 00:43:44.793014092 +0100 +@@ -2,7 +2,7 @@ + * SDIO spec header file + * Protocol and standard (common) device definitions + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/sdioh.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/sdioh.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/sdioh.h 2014-01-27 01:30:30.101433269 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/sdioh.h 2014-02-15 00:43:44.793014092 +0100 +@@ -2,7 +2,7 @@ + * SDIO Host Controller Spec header file + * Register map and definitions for the Standard Host Controller + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -22,7 +22,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: sdioh.h 345499 2012-07-18 06:59:05Z $ ++ * $Id: sdioh.h 347633 2012-07-27 11:02:02Z $ + */ + + #ifndef _SDIOH_H +@@ -90,8 +90,8 @@ + #define SD3_PresetVal_SDR104 0x06c + #define SD3_PresetVal_DDR50 0x06e + /* SDIO3.0 Revx specific Registers */ +-#define SD3_Tuning_Info_Register 0x0EC +-#define SD3_WL_BT_reset_register 0x0F0 ++#define SD3_Tuning_Info_Register 0x0EC ++#define SD3_WL_BT_reset_register 0x0F0 + + + /* preset value indices */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/sdiovar.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/sdiovar.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/sdiovar.h 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/sdiovar.h 2014-02-15 00:43:44.794014114 +0100 +@@ -2,7 +2,7 @@ + * Structure used by apps whose drivers access SDIO drivers. + * Pulled out separately so dhdu and wlu can both use it. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/siutils.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/siutils.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/siutils.h 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/siutils.h 2014-02-15 00:43:44.794014114 +0100 +@@ -2,7 +2,7 @@ + * Misc utility routines for accessing the SOC Interconnects + * of Broadcom HNBU chips. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -22,7 +22,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: siutils.h 385510 2013-02-15 21:02:07Z $ ++ * $Id: siutils.h 347614 2012-07-27 10:24:51Z $ + */ + + #ifndef _siutils_h_ +@@ -160,7 +160,6 @@ extern bool si_pci_war16165(si_t *sih); + extern uint si_corelist(si_t *sih, uint coreid[]); + extern uint si_coreid(si_t *sih); + extern uint si_flag(si_t *sih); +-extern uint si_flag_alt(si_t *sih); + extern uint si_intflag(si_t *sih); + extern uint si_coreidx(si_t *sih); + extern uint si_coreunit(si_t *sih); +@@ -171,8 +170,6 @@ extern void si_setosh(si_t *sih, osl_t * + extern uint si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val); + extern void *si_coreregs(si_t *sih); + extern uint si_wrapperreg(si_t *sih, uint32 offset, uint32 mask, uint32 val); +-extern uint si_core_wrapperreg(si_t *sih, uint32 coreidx, uint32 offset, uint32 mask, uint32 val); +-extern void *si_wrapperregs(si_t *sih); + extern uint32 si_core_cflags(si_t *sih, uint32 mask, uint32 val); + extern void si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val); + extern uint32 si_core_sflags(si_t *sih, uint32 mask, uint32 val); +@@ -190,7 +187,6 @@ extern int si_corebist(si_t *sih); + extern void si_core_reset(si_t *sih, uint32 bits, uint32 resetbits); + extern void si_core_disable(si_t *sih, uint32 bits); + extern uint32 si_clock_rate(uint32 pll_type, uint32 n, uint32 m); +-extern uint si_chip_hostif(si_t *sih); + extern bool si_read_pmu_autopll(si_t *sih); + extern uint32 si_clock(si_t *sih); + extern uint32 si_alp_clock(si_t *sih); +@@ -262,8 +258,6 @@ static INLINE void * si_eci_init(si_t *s + #define si_seci_upd(sih, a) do {} while (0) + static INLINE void * si_seci_init(si_t *sih, uint8 use_seci) {return NULL;} + #define si_seci_down(sih) do {} while (0) +-#define si_gci(sih) 0 +-static INLINE void * si_gci_init(si_t *sih) {return NULL;} + + /* OTP status */ + extern bool si_is_otp_disabled(si_t *sih); +@@ -303,8 +297,6 @@ extern char *si_coded_devpathvar(si_t *s + + extern uint8 si_pcieclkreq(si_t *sih, uint32 mask, uint32 val); + extern uint32 si_pcielcreg(si_t *sih, uint32 mask, uint32 val); +-extern uint8 si_pcieltrenable(si_t *sih, uint32 mask, uint32 val); +-extern void si_pcie_set_error_injection(si_t *sih, uint32 mode); + extern void si_war42780_clkreq(si_t *sih, bool clkreq); + extern void si_pci_down(si_t *sih); + extern void si_pci_up(si_t *sih); +@@ -328,7 +320,6 @@ extern void si_btc_enable_chipcontrol(si + extern void si_btcombo_p250_4313_war(si_t *sih); + extern void si_btcombo_43228_war(si_t *sih); + extern void si_clk_pmu_htavail_set(si_t *sih, bool set_clear); +-extern void si_pmu_synth_pwrsw_4313_war(si_t *sih); + extern uint si_pll_reset(si_t *sih); + /* === debug routines === */ + +@@ -336,13 +327,10 @@ extern bool si_taclear(si_t *sih, bool d + + + +-extern uint32 si_ccreg(si_t *sih, uint32 offset, uint32 mask, uint32 val); + extern uint32 si_pciereg(si_t *sih, uint32 offset, uint32 mask, uint32 val, uint type); + extern uint32 si_pcieserdesreg(si_t *sih, uint32 mdioslave, uint32 offset, uint32 mask, uint32 val); + extern void si_pcie_set_request_size(si_t *sih, uint16 size); + extern uint16 si_pcie_get_request_size(si_t *sih); +-extern void si_pcie_set_maxpayload_size(si_t *sih, uint16 size); +-extern uint16 si_pcie_get_maxpayload_size(si_t *sih); + extern uint16 si_pcie_get_ssid(si_t *sih); + extern uint32 si_pcie_get_bar0(si_t *sih); + extern int si_pcie_configspace_cache(si_t *sih); +@@ -356,27 +344,4 @@ extern uint32 si_tcm_size(si_t *sih); + + extern int si_set_sromctl(si_t *sih, uint32 value); + extern uint32 si_get_sromctl(si_t *sih); +- +-extern uint32 si_gci_direct(si_t *sih, uint offset, uint32 mask, uint32 val); +-extern void si_gci_reset(si_t *sih); +-extern void si_gci_set_functionsel(si_t *sih, uint32 pin, uint8 fnsel); +-extern uint8 si_gci_get_chipctrlreg_idx(uint32 pin, uint32 *regidx, uint32 *pos); +-extern uint32 si_gci_chipcontrol(si_t *sih, uint reg, uint32 mask, uint32 val); +- +-#define CHIPCTRLREG2 0x2 +-#define CHIPCTRLREG3 0x3 +-#define CHIPCTRLREG4 0x4 +-#define MINRESMASKREG 0x618 +-#define CHIPCTRLADDR 0x650 +-#define CHIPCTRLDATA 0x654 +-#define RSRCTABLEADDR 0x620 +-#define RSRCUPDWNTIME 0x628 +-#define PMUREG_RESREQ_MASK 0x68c +- +-void +-si_update_masks(si_t *sih); +- +-void +-si_force_islanding(si_t *sih, bool enable); +- + #endif /* _siutils_h_ */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/trxhdr.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/trxhdr.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/trxhdr.h 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/trxhdr.h 2014-02-15 00:43:44.794014114 +0100 +@@ -1,7 +1,7 @@ + /* + * TRX image file header format. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -21,7 +21,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: trxhdr.h 349211 2012-08-07 09:45:24Z $ ++ * $Id: trxhdr.h 260898 2011-05-20 23:11:12Z $ + */ + + #ifndef _TRX_HDR_H +@@ -30,62 +30,23 @@ + #include + + #define TRX_MAGIC 0x30524448 /* "HDR0" */ ++#define TRX_VERSION 1 /* Version 1 */ + #define TRX_MAX_LEN 0x3B0000 /* Max length */ + #define TRX_NO_HEADER 1 /* Do not write TRX header */ + #define TRX_GZ_FILES 0x2 /* Contains up to TRX_MAX_OFFSET individual gzip files */ + #define TRX_EMBED_UCODE 0x8 /* Trx contains embedded ucode image */ + #define TRX_ROMSIM_IMAGE 0x10 /* Trx contains ROM simulation image */ + #define TRX_UNCOMP_IMAGE 0x20 /* Trx contains uncompressed rtecdc.bin image */ +-#define TRX_BOOTLOADER 0x40 /* the image is a bootloader */ ++#define TRX_MAX_OFFSET 3 /* Max number of individual files */ + +-#define TRX_V1 1 +-#define TRX_V1_MAX_OFFSETS 3 /* V1: Max number of individual files */ +- +-#ifndef BCMTRXV2 +-#define TRX_VERSION TRX_V1 /* Version 1 */ +-#define TRX_MAX_OFFSET TRX_V1_MAX_OFFSETS +-#endif +- +-/* BMAC Host driver/application like bcmdl need to support both Ver 1 as well as +- * Ver 2 of trx header. To make it generic, trx_header is structure is modified +- * as below where size of "offsets" field will vary as per the TRX version. +- * Currently, BMAC host driver and bcmdl are modified to support TRXV2 as well. +- * To make sure, other applications like "dhdl" which are yet to be enhanced to support +- * TRXV2 are not broken, new macro and structure defintion take effect only when BCMTRXV2 +- * is defined. +- */ + struct trx_header { + uint32 magic; /* "HDR0" */ + uint32 len; /* Length of file including header */ + uint32 crc32; /* 32-bit CRC from flag_version to end of file */ + uint32 flag_version; /* 0:15 flags, 16:31 version */ +-#ifndef BCMTRXV2 + uint32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of header */ +-#else +- uint32 offsets[1]; /* Offsets of partitions from start of header */ +-#endif + }; + +-#ifdef BCMTRXV2 +-#define TRX_VERSION TRX_V2 /* Version 2 */ +-#define TRX_MAX_OFFSET TRX_V2_MAX_OFFSETS +- +-#define TRX_V2 2 +-/* V2: Max number of individual files +- * To support SDR signature + Config data region +- */ +-#define TRX_V2_MAX_OFFSETS 5 +-#define SIZEOF_TRXHDR_V1 (sizeof(struct trx_header)+(TRX_V1_MAX_OFFSETS-1)*sizeof(uint32)) +-#define SIZEOF_TRXHDR_V2 (sizeof(struct trx_header)+(TRX_V2_MAX_OFFSETS-1)*sizeof(uint32)) +-#define TRX_VER(trx) (trx->flag_version>>16) +-#define ISTRX_V1(trx) (TRX_VER(trx) == TRX_V1) +-#define ISTRX_V2(trx) (TRX_VER(trx) == TRX_V2) +-/* For V2, return size of V2 size: others, return V1 size */ +-#define SIZEOF_TRX(trx) (ISTRX_V2(trx) ? SIZEOF_TRXHDR_V2: SIZEOF_TRXHDR_V1) +-#else +-#define SIZEOF_TRX(trx) (sizeof(struct trx_header)) +-#endif /* BCMTRXV2 */ +- + /* Compatibility */ + typedef struct trx_header TRXHDR, *PTRXHDR; + +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/typedefs.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/typedefs.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/typedefs.h 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/typedefs.h 2014-02-15 00:43:44.794014114 +0100 +@@ -1,5 +1,5 @@ + /* +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -18,7 +18,7 @@ + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. +- * $Id: typedefs.h 397286 2013-04-18 01:42:19Z $ ++ * $Id: typedefs.h 286783 2011-09-29 06:18:57Z $ + */ + + #ifndef _TYPEDEFS_H_ +@@ -121,7 +121,7 @@ typedef long unsigned int size_t; + #if defined(__GNUC__) && defined(__STRICT_ANSI__) + #define TYPEDEF_INT64 + #define TYPEDEF_UINT64 +-#endif /* defined(__GNUC__) && defined(__STRICT_ANSI__) */ ++#endif + + /* ICL accepts unsigned 64 bit type only, and complains in ANSI mode + * for signed or unsigned +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/usbrdl.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/usbrdl.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/usbrdl.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/usbrdl.h 2014-02-15 00:43:44.794014114 +0100 +@@ -0,0 +1,114 @@ ++/* ++ * Broadcom USB remote download definitions ++ * ++ * Copyright (C) 2012, Broadcom Corporation ++ * All Rights Reserved. ++ * ++ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; ++ * the contents of this file may not be disclosed to third parties, copied ++ * or duplicated in any form, in whole or in part, without the prior ++ * written permission of Broadcom Corporation. ++ * ++ * $Id: usbrdl.h 296577 2011-11-16 03:09:51Z $ ++ */ ++ ++#ifndef _USB_RDL_H ++#define _USB_RDL_H ++ ++ ++#define DL_GETSTATE 0 ++#define DL_CHECK_CRC 1 ++#define DL_GO 2 ++#define DL_START 3 ++#define DL_REBOOT 4 ++#define DL_GETVER 5 ++#define DL_GO_PROTECTED 6 ++#define DL_EXEC 7 ++#define DL_RESETCFG 8 ++#define DL_DEFER_RESP_OK 9 ++ ++#define DL_HWCMD_MASK 0xfc ++#define DL_RDHW 0x10 ++#define DL_RDHW32 0x10 ++#define DL_RDHW16 0x11 ++#define DL_RDHW8 0x12 ++#define DL_WRHW 0x14 ++#define DL_WRHW_BLK 0x13 ++ ++#define DL_CMD_RDHW 1 ++#define DL_CMD_WRHW 2 ++ ++ ++ ++#define DL_WAITING 0 ++#define DL_READY 1 ++#define DL_BAD_HDR 2 ++#define DL_BAD_CRC 3 ++#define DL_RUNNABLE 4 ++#define DL_START_FAIL 5 ++#define DL_NVRAM_TOOBIG 6 ++#define DL_IMAGE_TOOBIG 7 ++ ++#define TIMEOUT 5000 ++ ++struct bcm_device_id { ++ char *name; ++ uint32 vend; ++ uint32 prod; ++}; ++ ++typedef struct { ++ uint32 state; ++ uint32 bytes; ++} rdl_state_t; ++ ++typedef struct { ++ uint32 chip; ++ uint32 chiprev; ++ uint32 ramsize; ++ uint32 remapbase; ++ uint32 boardtype; ++ uint32 boardrev; ++} bootrom_id_t; ++ ++ ++typedef struct { ++ uint32 cmd; ++ uint32 addr; ++ uint32 len; ++ uint32 data; ++} hwacc_t; ++ ++ ++typedef struct { ++ uint32 cmd; ++ uint32 addr; ++ uint32 len; ++ uint8 data[1]; ++} hwacc_blk_t; ++ ++ ++ ++#define QUERY_STRING_MAX 32 ++typedef struct { ++ uint32 cmd; ++ char var[QUERY_STRING_MAX]; ++} nvparam_t; ++ ++typedef void (*exec_fn_t)(void *sih); ++ ++#define USB_CTRL_IN (USB_TYPE_VENDOR | 0x80 | USB_RECIP_INTERFACE) ++#define USB_CTRL_OUT (USB_TYPE_VENDOR | 0 | USB_RECIP_INTERFACE) ++ ++#define USB_CTRL_EP_TIMEOUT 500 ++ ++#define RDL_CHUNK 1500 ++ ++ ++#define TRX_OFFSETS_DLFWLEN_IDX 0 ++#define TRX_OFFSETS_JUMPTO_IDX 1 ++#define TRX_OFFSETS_NVM_LEN_IDX 2 ++ ++#define TRX_OFFSETS_DLBASE_IDX 0 ++ ++#endif +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/wlfc_proto.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/wlfc_proto.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/wlfc_proto.h 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/wlfc_proto.h 2014-02-15 00:43:44.794014114 +0100 +@@ -1,5 +1,5 @@ + /* +-* Copyright (C) 1999-2013, Broadcom Corporation ++* Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -18,7 +18,7 @@ + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. +-* $Id: wlfc_proto.h 381382 2013-01-27 07:13:00Z $ ++* $Id: wlfc_proto.h 361006 2012-10-05 07:45:51Z $ + * + */ + #ifndef __wlfc_proto_definitions_h__ +@@ -34,8 +34,7 @@ + --------------------------------------------------------------------------- + | 3 | 2 | (count, handle, prec_bmp)| Set the credit depth for a MAC dstn + --------------------------------------------------------------------------- +- | 4 | 4+ | see pkttag comments | TXSTATUS +- | | | TX status & timestamps | Present only when pkt timestamp is enabled ++ | 4 | 4 | see pkttag comments | TXSTATUS + --------------------------------------------------------------------------- + | 5 | 4 | see pkttag comments | PKKTTAG [host->firmware] + --------------------------------------------------------------------------- +@@ -63,9 +62,11 @@ + | 13 | 3 | (count, handle, prec_bmp)| One time request for packet to a specific + | | | | MAC destination. + --------------------------------------------------------------------------- +- | 15 | 12 | (pkttag, timestamps) | Send TX timestamp at reception from host ++ | 15 | 1 | interface ID | NIC period start + --------------------------------------------------------------------------- +- | 16 | 12 | (pkttag, timestamps) | Send WLAN RX timestamp along with RX frame ++ | 16 | 1 | interface ID | NIC period end ++ --------------------------------------------------------------------------- ++ | 17 | 3 | (ifid, txs) | Action frame tx status + --------------------------------------------------------------------------- + | 255 | N/A | N/A | FILLER - This is a special type + | | | | that has no length or value. +@@ -81,7 +82,7 @@ + + #define WLFC_CTL_TYPE_MACDESC_ADD 6 + #define WLFC_CTL_TYPE_MACDESC_DEL 7 +-#define WLFC_CTL_TYPE_RSSI 8 ++#define WLFC_CTL_TYPE_RSSI 8 + + #define WLFC_CTL_TYPE_INTERFACE_OPEN 9 + #define WLFC_CTL_TYPE_INTERFACE_CLOSE 10 +@@ -92,12 +93,11 @@ + #define WLFC_CTL_TYPE_MAC_REQUEST_PACKET 13 + #define WLFC_CTL_TYPE_HOST_REORDER_RXPKTS 14 + +-#define WLFC_CTL_TYPE_TX_ENTRY_STAMP 15 +-#define WLFC_CTL_TYPE_RX_STAMP 16 +- +-#define WLFC_CTL_TYPE_TRANS_ID 18 +-#define WLFC_CTL_TYPE_COMP_TXSTATUS 19 +- ++#define WLFC_CTL_TYPE_NIC_PRD_START 15 ++#define WLFC_CTL_TYPE_NIC_PRD_END 16 ++#define WLFC_CTL_TYPE_AF_TXS 17 ++#define WLFC_CTL_TYPE_TRANS_ID 18 ++#define WLFC_CTL_TYPE_COMP_TXSTATUS 19 + + #define WLFC_CTL_TYPE_FILLER 255 + +@@ -118,6 +118,10 @@ + #define WLFC_CTL_VALUE_LEN_REQUEST_CREDIT 3 /* credit, MAC-handle, prec_bitmap */ + #define WLFC_CTL_VALUE_LEN_REQUEST_PACKET 3 /* credit, MAC-handle, prec_bitmap */ + ++#define WLFC_CTL_VALUE_LEN_NIC_PRD_START 1 ++#define WLFC_CTL_VALUE_LEN_NIC_PRD_END 1 ++#define WLFC_CTL_VALUE_LEN_AF_TXS 3 ++ + + #define WLFC_PKTID_GEN_MASK 0x80000000 + #define WLFC_PKTID_GEN_SHIFT 31 +@@ -223,8 +227,7 @@ + #define WLHOST_REORDERDATA_CURIDX_VALID 0x04 + #define WLHOST_REORDERDATA_EXPIDX_VALID 0x08 + #define WLHOST_REORDERDATA_NEW_HOLE 0x10 +- + /* transaction id data len byte 0: rsvd, byte 1: seqnumber, byte 2-5 will be used for timestampe */ +-#define WLFC_CTL_TRANS_ID_LEN 6 ++#define WLFC_CTL_TRANS_ID_LEN 6 + + #endif /* __wlfc_proto_definitions_h__ */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/include/wlioctl.h linux-sunxi-new/drivers/net/wireless/bcmdhd/include/wlioctl.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/include/wlioctl.h 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/include/wlioctl.h 2014-02-15 00:43:44.794014114 +0100 +@@ -4,7 +4,7 @@ + * + * Definitions subject to change without notice. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -24,7 +24,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: wlioctl.h 419132 2013-08-19 21:33:05Z $ ++ * $Id: wlioctl.h 366141 2012-11-01 01:55:06Z $ + */ + + #ifndef _wlioctl_h_ +@@ -63,12 +63,6 @@ typedef struct remote_ioctl { + } rem_ioctl_t; + #define REMOTE_SIZE sizeof(rem_ioctl_t) + +- +-typedef struct { +- uint32 num; +- chanspec_t list[1]; +-} chanspec_list_t; +- + #define ACTION_FRAME_SIZE 1800 + + typedef struct wl_action_frame { +@@ -215,8 +209,8 @@ typedef struct wl_bss_info { + uint32 nbss_cap; /* 802.11N+AC BSS Capabilities */ + uint8 ctl_ch; /* 802.11N BSS control channel number */ + uint8 padding1[3]; /* explicit struct alignment padding */ +- uint16 vht_rxmcsmap; /* VHT rx mcs map (802.11ac VHT_CAP_MCS_MAP_*) */ +- uint16 vht_txmcsmap; /* VHT tx mcs map (802.11ac VHT_CAP_MCS_MAP_*) */ ++ uint16 vht_rxmcsmap; /* VHT rx mcs map */ ++ uint16 vht_txmcsmap; /* VHT tx mcs map */ + uint8 flags; /* flags */ + uint8 vht_cap; /* BSS is vht capable */ + uint8 reserved[2]; /* Reserved for expansion of BSS properties */ +@@ -310,7 +304,7 @@ typedef struct wl_clm_dload_info wl_clm_ + + typedef struct wlc_ssid { + uint32 SSID_len; +- uchar SSID[DOT11_MAX_SSID_LEN]; ++ uchar SSID[32]; + } wlc_ssid_t; + + #ifndef LINUX_POSTMOGRIFY_REMOVAL +@@ -364,8 +358,6 @@ typedef struct wl_extdscan_params { + #define WL_SCANFLAGS_PASSIVE 0x01 /* force passive scan */ + #define WL_SCANFLAGS_RESERVED 0x02 /* Reserved */ + #define WL_SCANFLAGS_PROHIBITED 0x04 /* allow scanning prohibited channels */ +-#define WL_SCANFLAGS_OFFCHAN 0x08 /* allow scanning/reporting off-channel APs */ +-#define WL_SCANFLAGS_HOTSPOT 0x10 /* automatic ANQP to hotspot APs */ + + #define WL_SCAN_PARAMS_SSID_MAX 10 + +@@ -498,7 +490,6 @@ typedef struct wl_rateset_args { + uint32 count; /* # rates in this set */ + uint8 rates[WL_MAXRATES_IN_SET]; /* rates in 500kbps units w/hi bit set if basic */ + uint8 mcs[MCSSET_LEN]; /* supported mcs index bit map */ +- uint16 vht_mcs[VHT_CAP_MCS_MAP_NSS_MAX]; /* supported mcs index bit map per nss */ + } wl_rateset_args_t; + + /* uint32 list */ +@@ -512,10 +503,10 @@ typedef struct wl_uint32_list { + /* used for association with a specific BSSID and chanspec list */ + typedef struct wl_assoc_params { + struct ether_addr bssid; /* 00:00:00:00:00:00: broadcast scan */ +- uint16 bssid_cnt; /* 0: use chanspec_num, and the single bssid, +- * otherwise count of chanspecs in chanspec_list +- * AND paired bssids following chanspec_list +- */ ++ uint16 bssid_cnt; /* 0: use chanspec_num, and the single bssid, ++ * otherwise count of chanspecs in chanspec_list ++ * AND paired bssids following chanspec_list ++ */ + int32 chanspec_num; /* 0: all available channels, + * otherwise count of chanspecs in chanspec_list + */ +@@ -604,7 +595,6 @@ typedef struct wl_extjoin_params { + #define WL_RSPEC_BW_MASK 0x00070000 /* bandwidth mask */ + #define WL_RSPEC_BW_SHIFT 16 /* bandwidth shift */ + #define WL_RSPEC_STBC 0x00100000 /* STBC encoding, Nsts = 2 x Nss */ +-#define WL_RSPEC_TXBF 0x00200000 /* bit indicates TXBF mode */ + #define WL_RSPEC_LDPC 0x00400000 /* bit indicates adv coding in use */ + #define WL_RSPEC_SGI 0x00800000 /* Short GI mode */ + #define WL_RSPEC_ENCODING_MASK 0x03000000 /* Encoding of Rate/MCS field */ +@@ -865,8 +855,10 @@ typedef enum sup_auth_status { + #define CRYPTO_ALGO_WEP_MMH 9 + #define CRYPTO_ALGO_NALG 10 + #endif ++#ifdef BCMWAPI_WPI ++#define CRYPTO_ALGO_SMS4 11 ++#endif /* BCMWAPI_WPI */ + #define CRYPTO_ALGO_PMK 12 /* for 802.1x supp to set PMK before 4-way */ +-#define CRYPTO_ALGO_BIP 13 /* 802.11w BIP (aes cmac) */ + + #define WSEC_GEN_MIC_ERROR 0x0001 + #define WSEC_GEN_REPLAY 0x0002 +@@ -933,10 +925,15 @@ typedef struct { + + #define WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED)) + #define WSEC_SES_OW_ENABLED(wsec) ((wsec) & SES_OW_ENABLED) ++#ifdef BCMWAPI_WPI ++#define SMS4_ENABLED 0x0100 ++#endif /* BCMWAPI_WPI */ + ++#ifdef MFP + #define MFP_CAPABLE 0x0200 + #define MFP_REQUIRED 0x0400 + #define MFP_SHA256 0x0800 /* a special configuration for STA for WIFI test tool */ ++#endif /* MFP */ + + /* WPA authentication mode bitvec */ + #define WPA_AUTH_DISABLED 0x0000 /* Legacy (i.e., non-WPA) */ +@@ -952,6 +949,12 @@ typedef struct { + #define WPA2_AUTH_PSK 0x0080 /* Pre-shared key */ + #define BRCM_AUTH_PSK 0x0100 /* BRCM specific PSK */ + #define BRCM_AUTH_DPT 0x0200 /* DPT PSK without group keys */ ++#ifdef BCMWAPI_WAI ++#define WPA_AUTH_WAPI 0x0400 ++#define WAPI_AUTH_NONE WPA_AUTH_NONE /* none (IBSS) */ ++#define WAPI_AUTH_UNSPECIFIED 0x0400 /* over AS */ ++#define WAPI_AUTH_PSK 0x0800 /* Pre-shared key */ ++#endif /* BCMWAPI_WAI */ + #define WPA2_AUTH_MFP 0x1000 /* MFP (11w) in contrast to CCX */ + #define WPA2_AUTH_TPK 0x2000 /* TDLS Peer Key */ + #define WPA2_AUTH_FT 0x4000 /* Fast Transition. */ +@@ -1055,32 +1058,6 @@ typedef struct wme_tx_params_s wme_tx_pa + + #define WL_WME_TX_PARAMS_IO_BYTES (sizeof(wme_tx_params_t) * AC_COUNT) + +-typedef struct wl_plc_nodelist { +- uint count; /* Number of nodes */ +- struct _node { +- struct ether_addr ea; /* Node ether address */ +- uint32 node_type; /* Node type */ +- uint32 cost; /* PLC affinity */ +- } node[1]; +-} wl_plc_nodelist_t; +- +-typedef struct wl_plc_params { +- uint32 cmd; /* Command */ +- bool plc_failover; /* PLC failover control/status */ +- struct ether_addr node_ea; /* Node ether address */ +- uint32 cost; /* Link cost or mac cost */ +-} wl_plc_params_t; +- +-#define PLC_CMD_FAILOVER 1 +-#define PLC_CMD_MAC_COST 2 +-#define PLC_CMD_LINK_COST 3 +-#define PLC_CMD_NODE_LIST 4 +- +-#define NODE_TYPE_UNKNOWN 0 /* Unknown link */ +-#define NODE_TYPE_WIFI_ONLY 1 /* Pure Wireless STA node */ +-#define NODE_TYPE_PLC_ONLY 2 /* Pure PLC only node */ +-#define NODE_TYPE_WIFI_PLC 3 /* WiFi PLC capable node */ +- + /* defines used by poweridx iovar - it controls power in a-band */ + /* current gain setting is maintained */ + #define WL_PWRIDX_PCL_OFF -2 /* turn off PCL. */ +@@ -1226,7 +1203,7 @@ typedef struct { + + /* Get MAC rate histogram response */ + typedef struct { +- uint32 rate[DOT11_RATE_MAX + 1]; /* Rates */ ++ uint32 rate[WLC_MAXRATE + 1]; /* Rates */ + uint32 mcs[WL_RATESET_SZ_HT_MCS * WL_TX_CHAINS_MAX]; /* MCS counts */ + uint32 vht[WL_RATESET_SZ_VHT_MCS][WL_TX_CHAINS_MAX]; /* VHT counts */ + uint32 tsf_timer[2][2]; /* Start and End time for 8bytes value */ +@@ -1284,7 +1261,6 @@ typedef struct wlc_rev_info { + uint phyrev; /* phy revision */ + uint anarev; /* anacore rev */ + uint chippkg; /* chip package info */ +- uint nvramrev; /* nvram revision number */ + } wlc_rev_info_t; + + #define WL_REV_INFO_LEGACY_LENGTH 48 +@@ -1618,9 +1594,7 @@ typedef struct wlc_iov_trx_s { + #define WLC_NVRAM_SET 265 + #define WLC_NVRAM_DUMP 266 + #define WLC_REBOOT 267 +-#endif /* LINUX_POSTMOGRIFY_REMOVAL */ + #define WLC_SET_WSEC_PMK 268 +-#ifndef LINUX_POSTMOGRIFY_REMOVAL + #define WLC_GET_AUTH_MODE 269 + #define WLC_SET_AUTH_MODE 270 + #define WLC_GET_WAKEENTRY 271 +@@ -1670,8 +1644,7 @@ typedef struct wlc_iov_trx_s { + /* #define WLC_SET_WAI_REKEY 315 */ /* for WAPI, deprecated use iovar instead */ + #define WLC_SET_NAT_CONFIG 316 /* for configuring NAT filter driver */ + #define WLC_GET_NAT_STATE 317 +-#define WLC_GET_RSSI_QDB 318 /* qdB portion of the RSSI */ +-#define WLC_LAST 319 ++#define WLC_LAST 318 + + #ifndef EPICTRL_COOKIE + #define EPICTRL_COOKIE 0xABADCEDE +@@ -1742,7 +1715,12 @@ typedef struct { + /* WLC_GET_AUTH, WLC_SET_AUTH values */ + #define WL_AUTH_OPEN_SYSTEM 0 /* d11 open authentication */ + #define WL_AUTH_SHARED_KEY 1 /* d11 shared authentication */ +-#define WL_AUTH_OPEN_SHARED 2 /* try open, then shared if open failed w/rc 13 */ ++#ifdef BCM4330_CHIP ++#define WL_AUTH_OPEN_SHARED 2 /* try open, then shared if open failed w/rc 13 */ ++#else ++/* BCM4334(Phoenex branch) value changed to 3 */ ++#define WL_AUTH_OPEN_SHARED 3 /* try open, then shared if open failed w/rc 13 */ ++#endif + #endif /* LINUX_POSTMOGRIFY_REMOVAL */ + + /* Bit masks for radio disabled status - returned by WL_GET_RADIO */ +@@ -1755,17 +1733,6 @@ typedef struct { + #define WL_SPURAVOID_ON1 1 + #define WL_SPURAVOID_ON2 2 + +- +-#define WL_4335_SPURAVOID_ON1 1 +-#define WL_4335_SPURAVOID_ON2 2 +-#define WL_4335_SPURAVOID_ON3 3 +-#define WL_4335_SPURAVOID_ON4 4 +-#define WL_4335_SPURAVOID_ON5 5 +-#define WL_4335_SPURAVOID_ON6 6 +-#define WL_4335_SPURAVOID_ON7 7 +-#define WL_4335_SPURAVOID_ON8 8 +-#define WL_4335_SPURAVOID_ON9 9 +- + /* Override bit for WLC_SET_TXPWR. if set, ignore other level limits */ + #define WL_TXPWR_OVERRIDE (1U<<31) + #define WL_TXPWR_NEG (1U<<30) +@@ -1774,16 +1741,6 @@ typedef struct { + #define WL_PHY_PAVARS_LEN 32 /* Phy type, Band range, chain, a1[0], b0[0], b1[0] ... */ + + #define WL_PHY_PAVAR_VER 1 /* pavars version */ +-#define WL_PHY_PAVARS2_NUM 3 /* a1, b0, b1 */ +-typedef struct wl_pavars2 { +- uint16 ver; /* version of this struct */ +- uint16 len; /* len of this structure */ +- uint16 inuse; /* driver return 1 for a1,b0,b1 in current band range */ +- uint16 phy_type; /* phy type */ +- uint16 bandrange; +- uint16 chain; +- uint16 inpa[WL_PHY_PAVARS2_NUM]; /* phy pavars for one band range */ +-} wl_pavars2_t; + + typedef struct wl_po { + uint16 phy_type; /* Phy type */ +@@ -1835,12 +1792,6 @@ typedef struct wl_po { + #define WL_CHAN_FREQ_RANGE_5GM 2 + #define WL_CHAN_FREQ_RANGE_5GH 3 + +-#define WL_CHAN_FREQ_RANGE_5GLL_5BAND 4 +-#define WL_CHAN_FREQ_RANGE_5GLH_5BAND 5 +-#define WL_CHAN_FREQ_RANGE_5GML_5BAND 6 +-#define WL_CHAN_FREQ_RANGE_5GMH_5BAND 7 +-#define WL_CHAN_FREQ_RANGE_5GH_5BAND 8 +- + #define WL_CHAN_FREQ_RANGE_5G_BAND0 1 + #define WL_CHAN_FREQ_RANGE_5G_BAND1 2 + #define WL_CHAN_FREQ_RANGE_5G_BAND2 3 +@@ -2041,8 +1992,6 @@ typedef struct wl_samplecollect_args { + uint8 module_sel1; + uint8 module_sel2; + uint16 nsamps; +- int bitStart; +- uint32 gpioCapMask; + } wl_samplecollect_args_t; + + #define WL_SAMPLEDATA_HEADER_TYPE 1 +@@ -2062,117 +2011,6 @@ typedef struct wl_sampledata { + uint32 flag; /* bit def */ + } wl_sampledata_t; + +-/* WL_OTA START */ +- +-#define WL_OTA_ARG_PARSE_BLK_SIZE 1200 +-#define WL_OTA_TEST_MAX_NUM_RATE 30 +-#define WL_OTA_TEST_MAX_NUM_SEQ 100 +- +-/* OTA Test Status */ +-enum { +- WL_OTA_TEST_IDLE, /* Default Idle state */ +- WL_OTA_TEST_ACTIVE, /* Test Running */ +- WL_OTA_TEST_SUCCESS, /* Successfully Finished Test */ +- WL_OTA_TEST_FAIL /* Test Failed in the Middle */ +-}; +-/* OTA SYNC Status */ +-enum { +- WL_OTA_SYNC_IDLE, /* Idle state */ +- WL_OTA_SYNC_ACTIVE, /* Waiting for Sync */ +- WL_OTA_SYNC_FAIL /* Sync pkt not recieved */ +-}; +- +-/* Various error states dut can get stuck during test */ +-enum { +- WL_OTA_SKIP_TEST_CAL_FAIL = 1, /* Phy calibration failed */ +- WL_OTA_SKIP_TEST_SYNCH_FAIL, /* Sync Packet not recieved */ +- WL_OTA_SKIP_TEST_FILE_DWNLD_FAIL, /* Cmd flow file download failed */ +- WL_OTA_SKIP_TEST_NO_TEST_FOUND, /* No test found in Flow file */ +- WL_OTA_SKIP_TEST_WL_NOT_UP, /* WL UP failed */ +- WL_OTA_SKIP_TEST_UNKNOWN_CALL /* Unintentional scheduling on ota test */ +-}; +- +-/* Differentiator for ota_tx and ota_rx */ +-enum { +- WL_OTA_TEST_TX, /* ota_tx */ +- WL_OTA_TEST_RX /* ota_rx */ +-}; +- +-/* Catch 3 modes of operation: 20Mhz, 40Mhz, 20 in 40 Mhz */ +-enum { +- WL_OTA_TEST_BW_20_IN_40MHZ, /* 20 in 40 operation */ +- WL_OTA_TEST_BW_20MHZ, /* 20 Mhz operation */ +- WL_OTA_TEST_BW_40MHZ /* full 40Mhz operation */ +-}; +-typedef struct ota_rate_info { +- uint8 rate_cnt; /* Total number of rates */ +- uint8 rate_val_mbps[WL_OTA_TEST_MAX_NUM_RATE]; /* array of rates from 1mbps to 130mbps */ +- /* for legacy rates : ratein mbps * 2 */ +- /* for HT rates : mcs index */ +-} ota_rate_info_t; +- +-typedef struct ota_power_info { +- int8 pwr_ctrl_on; /* power control on/off */ +- int8 start_pwr; /* starting power/index */ +- int8 delta_pwr; /* delta power/index */ +- int8 end_pwr; /* end power/index */ +-} ota_power_info_t; +- +-typedef struct ota_packetengine { +- uint16 delay; /* Inter-packet delay */ +- /* for ota_tx, delay is tx ifs in micro seconds */ +- /* for ota_rx, delay is wait time in milliseconds */ +- uint16 nframes; /* Number of frames */ +- uint16 length; /* Packet length */ +-} ota_packetengine_t; +- +-/* Test info vector */ +-typedef struct wl_ota_test_args { +- uint8 cur_test; /* test phase */ +- uint8 chan; /* channel */ +- uint8 bw; /* bandwidth */ +- char control_band; /* control band */ +- uint8 stf_mode; /* stf mode */ +- ota_rate_info_t rt_info; /* Rate info */ +- ota_packetengine_t pkteng; /* packeteng info */ +- uint8 txant; /* tx antenna */ +- uint8 rxant; /* rx antenna */ +- ota_power_info_t pwr_info; /* power sweep info */ +- uint8 wait_for_sync; /* wait for sync or not */ +-} wl_ota_test_args_t; +- +-typedef struct wl_ota_test_vector { +- wl_ota_test_args_t test_arg[WL_OTA_TEST_MAX_NUM_SEQ]; /* Test argument struct */ +- uint16 test_cnt; /* Total no of test */ +- bool file_dwnld_valid; /* File successfully downloaded */ +- uint8 sync_timeout; /* sync packet timeout */ +- int8 sync_fail_action; /* sync fail action */ +- struct ether_addr sync_mac; /* macaddress for sync pkt */ +- struct ether_addr tx_mac; /* macaddress for tx */ +- struct ether_addr rx_mac; /* macaddress for rx */ +- int8 loop_test; /* dbg feature to loop the test */ +-} wl_ota_test_vector_t; +- +- +-/* struct copied back form dongle to host to query the status */ +-typedef struct wl_ota_test_status { +- int16 cur_test_cnt; /* test phase */ +- int8 skip_test_reason; /* skip test reasoin */ +- wl_ota_test_args_t test_arg; /* cur test arg details */ +- uint16 test_cnt; /* total no of test downloaded */ +- bool file_dwnld_valid; /* file successfully downloaded ? */ +- uint8 sync_timeout; /* sync timeout */ +- int8 sync_fail_action; /* sync fail action */ +- struct ether_addr sync_mac; /* macaddress for sync pkt */ +- struct ether_addr tx_mac; /* tx mac address */ +- struct ether_addr rx_mac; /* rx mac address */ +- uint8 test_stage; /* check the test status */ +- int8 loop_test; /* Debug feature to puts test enfine in a loop */ +- uint8 sync_status; /* sync status */ +-} wl_ota_test_status_t; +- +-/* WL_OTA END */ +- + /* wl_radar_args_t */ + typedef struct { + int npulses; /* required number of pulses at n * t_int */ +@@ -2352,168 +2190,168 @@ typedef struct { + + typedef struct txppr { + /* start of 20MHz tx power limits */ +- int8 b20_1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ +- int8 b20_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ +- int8 b20_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ +- +- int8 b20_1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ +- int8 b20_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ +- int8 b20_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ +- int8 b20_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ +- int8 b20_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ +- +- int8 b20_1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ +- int8 b20_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ +- int8 b20_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ +- int8 b20_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ +- int8 b20_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ +- int8 b20_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ +- +- int8 b20_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ +- int8 b20_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ +- int8 b20_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ +- int8 b20_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ +- int8 b20_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ +- int8 b20_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ +- int8 b20_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ +- int8 b20_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ ++ uint8 b20_1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ ++ uint8 b20_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ ++ ++ uint8 b20_1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b20_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ ++ uint8 b20_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b20_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ ++ ++ uint8 b20_1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b20_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ ++ uint8 b20_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b20_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ ++ uint8 b20_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ ++ ++ uint8 b20_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ ++ uint8 b20_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ ++ uint8 b20_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ ++ uint8 b20_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ ++ uint8 b20_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ ++ uint8 b20_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ ++ uint8 b20_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ ++ uint8 b20_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ + + /* start of 40MHz tx power limits */ +- int8 b40_dummy1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ +- int8 b40_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ +- int8 b40_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ +- +- int8 b40_dummy1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ +- int8 b40_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ +- int8 b40_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ +- int8 b40_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ +- int8 b40_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ +- +- int8 b40_dummy1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ +- int8 b40_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ +- int8 b40_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ +- int8 b40_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ +- int8 b40_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ +- int8 b40_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ +- +- int8 b40_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ +- int8 b40_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ +- int8 b40_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ +- int8 b40_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ +- int8 b40_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ +- int8 b40_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ +- int8 b40_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ +- int8 b40_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ ++ uint8 b40_dummy1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b40_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ ++ uint8 b40_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ ++ ++ uint8 b40_dummy1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b40_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b40_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ ++ uint8 b40_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b40_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ ++ ++ uint8 b40_dummy1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b40_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b40_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ ++ uint8 b40_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b40_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ ++ uint8 b40_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ ++ ++ uint8 b40_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ ++ uint8 b40_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ ++ uint8 b40_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ ++ uint8 b40_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ ++ uint8 b40_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ ++ uint8 b40_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ ++ uint8 b40_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ ++ uint8 b40_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ + + /* start of 20in40MHz tx power limits */ +- int8 b20in40_1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ +- int8 b20in40_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ +- int8 b20in40_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ +- +- int8 b20in40_1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ +- int8 b20in40_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ +- int8 b20in40_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ +- int8 b20in40_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ +- int8 b20in40_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ +- +- int8 b20in40_1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ +- int8 b20in40_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* 20 in 40 MHz Legacy OFDM CDD */ +- int8 b20in40_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ +- int8 b20in40_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ +- int8 b20in40_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ +- int8 b20in40_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ +- +- int8 b20in40_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ +- int8 b20in40_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ +- int8 b20in40_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ +- int8 b20in40_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ +- int8 b20in40_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ +- int8 b20in40_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ +- int8 b20in40_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ +- int8 b20in40_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ ++ uint8 b20in40_1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20in40_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ ++ uint8 b20in40_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ ++ ++ uint8 b20in40_1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20in40_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b20in40_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ ++ uint8 b20in40_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b20in40_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ ++ ++ uint8 b20in40_1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20in40_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* 20 in 40 MHz Legacy OFDM CDD */ ++ uint8 b20in40_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ ++ uint8 b20in40_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b20in40_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ ++ uint8 b20in40_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ ++ ++ uint8 b20in40_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ ++ uint8 b20in40_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ ++ uint8 b20in40_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ ++ uint8 b20in40_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ ++ uint8 b20in40_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ ++ uint8 b20in40_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ ++ uint8 b20in40_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ ++ uint8 b20in40_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ + + /* start of 80MHz tx power limits */ +- int8 b80_dummy1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ +- int8 b80_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ +- int8 b80_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ +- +- int8 b80_dummy1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ +- int8 b80_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ +- int8 b80_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ +- int8 b80_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ +- int8 b80_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ +- +- int8 b80_dummy1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ +- int8 b80_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ +- int8 b80_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ +- int8 b80_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ +- int8 b80_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ +- int8 b80_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ +- +- int8 b80_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ +- int8 b80_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ +- int8 b80_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ +- int8 b80_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ +- int8 b80_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ +- int8 b80_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ +- int8 b80_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ +- int8 b80_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ ++ uint8 b80_dummy1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b80_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ ++ uint8 b80_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ ++ ++ uint8 b80_dummy1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b80_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b80_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ ++ uint8 b80_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b80_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ ++ ++ uint8 b80_dummy1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b80_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b80_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ ++ uint8 b80_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b80_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ ++ uint8 b80_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ ++ ++ uint8 b80_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ ++ uint8 b80_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ ++ uint8 b80_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ ++ uint8 b80_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ ++ uint8 b80_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ ++ uint8 b80_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ ++ uint8 b80_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ ++ uint8 b80_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ + + /* start of 20in80MHz tx power limits */ +- int8 b20in80_1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ +- int8 b20in80_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ +- int8 b20in80_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ +- +- int8 b20in80_1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ +- int8 b20in80_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ +- int8 b20in80_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ +- int8 b20in80_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ +- int8 b20in80_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ +- +- int8 b20in80_1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ +- int8 b20in80_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ +- int8 b20in80_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ +- int8 b20in80_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ +- int8 b20in80_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ +- int8 b20in80_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ +- +- int8 b20in80_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ +- int8 b20in80_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ +- int8 b20in80_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ +- int8 b20in80_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ +- int8 b20in80_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ +- int8 b20in80_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ +- int8 b20in80_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ +- int8 b20in80_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ ++ uint8 b20in80_1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20in80_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ ++ uint8 b20in80_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ ++ ++ uint8 b20in80_1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20in80_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b20in80_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ ++ uint8 b20in80_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b20in80_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ ++ ++ uint8 b20in80_1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b20in80_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b20in80_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ ++ uint8 b20in80_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b20in80_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ ++ uint8 b20in80_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ ++ ++ uint8 b20in80_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ ++ uint8 b20in80_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ ++ uint8 b20in80_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ ++ uint8 b20in80_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ ++ uint8 b20in80_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ ++ uint8 b20in80_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ ++ uint8 b20in80_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ ++ uint8 b20in80_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ + + /* start of 40in80MHz tx power limits */ +- int8 b40in80_dummy1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ +- int8 b40in80_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ +- int8 b40in80_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ +- +- int8 b40in80_dummy1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ +- int8 b40in80_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ +- int8 b40in80_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ +- int8 b40in80_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ +- int8 b40in80_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ +- +- int8 b40in80_dummy1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ +- int8 b40in80_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* MHz Legacy OFDM CDD */ +- int8 b40in80_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ +- int8 b40in80_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ +- int8 b40in80_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ +- int8 b40in80_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ +- +- int8 b40in80_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ +- int8 b40in80_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ +- int8 b40in80_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ +- int8 b40in80_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ +- int8 b40in80_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ +- int8 b40in80_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ +- int8 b40in80_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ +- int8 b40in80_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ ++ uint8 b40in80_dummy1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b40in80_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ ++ uint8 b40in80_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ ++ ++ uint8 b40in80_dummy1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b40in80_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ ++ uint8 b40in80_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ ++ uint8 b40in80_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b40in80_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ ++ ++ uint8 b40in80_dummy1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ ++ uint8 b40in80_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* MHz Legacy OFDM CDD */ ++ uint8 b40in80_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ ++ uint8 b40in80_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ ++ uint8 b40in80_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ ++ uint8 b40in80_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ ++ ++ uint8 b40in80_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ ++ uint8 b40in80_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ ++ uint8 b40in80_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ ++ uint8 b40in80_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ ++ uint8 b40in80_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ ++ uint8 b40in80_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ ++ uint8 b40in80_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ ++ uint8 b40in80_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ + +- int8 mcs32; /* C_CHECK - THIS NEEDS TO BE REMOVED THROUGHOUT THE CODE */ ++ uint8 mcs32; /* C_CHECK - THIS NEEDS TO BE REMOVED THROUGHOUT THE CODE */ + } txppr_t; + + /* 20MHz */ +@@ -2695,35 +2533,45 @@ typedef struct txppr { + #define WL_TX_POWER_MCS20_SISO_FIRST_SSN WL_TX_POWER_MCS20_SISO_FIRST + #define WL_TX_POWER_MCS40_SISO_FIRST_SSN WL_TX_POWER_MCS40_SISO_FIRST + ++/* tx_power_t.flags bits */ ++#define WL_TX_POWER_F_ENABLED 1 ++#define WL_TX_POWER_F_HW 2 ++#define WL_TX_POWER_F_MIMO 4 ++#define WL_TX_POWER_F_SISO 8 ++#define WL_TX_POWER_F_HT 0x10 ++ + typedef struct { + uint16 ver; /* version of this struct */ + uint16 len; /* length in bytes of this structure */ + uint32 flags; + chanspec_t chanspec; /* txpwr report for this channel */ + chanspec_t local_chanspec; /* channel on which we are associated */ +- uint32 buflen; /* ppr buffer length */ +- uint8 pprbuf[1]; /* Latest target power buffer */ ++ uint8 ppr[WL_TX_POWER_RATES]; /* Latest target power */ + } wl_txppr_t; + + #define WL_TXPPR_VERSION 0 + #define WL_TXPPR_LENGTH (sizeof(wl_txppr_t)) +-#define TX_POWER_T_VERSION 44 ++#define TX_POWER_T_VERSION 43 + + /* Defines used with channel_bandwidth for curpower */ + #define WL_BW_20MHZ 0 + #define WL_BW_40MHZ 1 + #define WL_BW_80MHZ 2 +-#define WL_BW_160MHZ 3 + + /* tx_power_t.flags bits */ +-/* use for defined PPR_API */ ++#ifdef PPR_API ++#define WL_TX_POWER2_F_ENABLED 1 ++#define WL_TX_POWER2_F_HW 2 ++#define WL_TX_POWER2_F_MIMO 4 ++#define WL_TX_POWER2_F_SISO 8 ++#define WL_TX_POWER2_F_HT 0x10 ++#else + #define WL_TX_POWER_F_ENABLED 1 + #define WL_TX_POWER_F_HW 2 + #define WL_TX_POWER_F_MIMO 4 + #define WL_TX_POWER_F_SISO 8 + #define WL_TX_POWER_F_HT 0x10 +-#define WL_TX_POWER_F_VHT 0x20 +- ++#endif + typedef struct { + uint32 flags; + chanspec_t chanspec; /* txpwr report for this channel */ +@@ -2733,7 +2581,9 @@ typedef struct { + int8 antgain[2]; /* Ant gain for each band - from SROM */ + uint8 rf_cores; /* count of RF Cores being reported */ + uint8 est_Pout[4]; /* Latest tx power out estimate per RF chain */ +- uint8 est_Pout_act[4]; /* Latest tx power out estimate per RF chain w/o adjustment */ ++ uint8 est_Pout_act[4]; /* Latest tx power out estimate per RF chain ++ * without adjustment ++ */ + uint8 est_Pout_cck; /* Latest CCK tx power out estimate */ + uint8 tx_power_max[4]; /* Maximum target power among all rates */ + uint tx_power_max_rate_ind[4]; /* Index of the rate with the max target power */ +@@ -2747,10 +2597,11 @@ typedef struct { + int8 channel_bandwidth; /* 20, 40 or 80 MHz bandwidth? */ + uint8 version; /* Version of the data format wlu <--> driver */ + uint8 display_core; /* Displayed curpower core */ +- int8 target_offsets[4]; /* Target power offsets for current rate per core */ +- uint32 last_tx_ratespec; /* Ratespec for last transmition */ +- int8 SARLIMIT[MAX_STREAMS_SUPPORTED]; ++#ifdef PPR_API ++} tx_power_new_t; ++#else + } tx_power_t; ++#endif + + typedef struct tx_inst_power { + uint8 txpwr_est_Pout[2]; /* Latest estimate for 2.4 and 5 Ghz */ +@@ -2893,20 +2744,7 @@ typedef struct wl_txchain_pwr_offsets { + #define WL_PSTA_VAL 0x00008000 + #define WL_TBTT_VAL 0x00010000 + #define WL_NIC_VAL 0x00020000 +-#define WL_PWRSEL_VAL 0x00040000 +-#define WL_TRF_MGMT_VAL 0x00080000 +-#define WL_L2FILTER_VAL 0x00100000 +-#define WL_TSO_VAL 0x00200000 +-#define WL_MQ_VAL 0x00400000 +-/* These 3 levels are currently not used in trunk but in Aardvark and Phoenix2 with != values */ +-#define WL_LPC_VAL 0x00800000 +-#define WL_TXBF_VAL 0x01000000 +-#define WL_P2PO_VAL 0x02000000 +-/* This level is synchronized with other branches */ +-#define WL_WNM_VAL 0x04000000 +-/* This level is currently not used in trunk but used in Phoenix2 */ +-#define WL_SRSCAN_VAL 0x08000000 +- ++#define WL_PWRSEL_VAL 0x00040000 + /* use top-bit for WL_TIME_STAMP_VAL because this is a modifier + * rather than a message-type of its own + */ +@@ -2939,9 +2777,7 @@ typedef struct wl_txchain_pwr_offsets { + #define WL_LED_ASSOC_WITH_SEC 20 /* when connected with security */ + /* keep on for 300 sec */ + #define WL_LED_START_OFF 21 /* off upon boot, could be turned on later */ +-#define WL_LED_W6 22 /* off upon boot, could be turned on later */ +-#define WL_LED_WI7 23 /* off upon boot, could be turned on later */ +-#define WL_LED_NUMBEHAVIOR 24 ++#define WL_LED_NUMBEHAVIOR 22 + + /* led behavior numeric value format */ + #define WL_LED_BEH_MASK 0x7f /* behavior mask */ +@@ -2999,7 +2835,7 @@ typedef struct wl_txchain_pwr_offsets { + * + * 4. BAND RSSI - 2 octets + * offset 0: band types +- * offset 1: +ve RSSI boost value in dB ++ * offset 1: +ve RSSI boost balue in dB + */ + + /* join preference types */ +@@ -3263,12 +3099,6 @@ typedef struct { + uint32 pstatxbcmc; /* count of bcmc frames transmitted on all psta */ + + uint32 cso_passthrough; /* hw cso required but passthrough */ +- uint32 chained; /* number of frames chained */ +- uint32 chainedsz1; /* number of chain size 1 frames */ +- uint32 unchained; /* number of frames not chained */ +- uint32 maxchainsz; /* max chain size so far */ +- uint32 currchainsz; /* current chain size */ +- uint32 cso_normal; /* hw cso hdr for normal process */ + } wl_cnt_t; + + #ifndef LINUX_POSTMOGRIFY_REMOVAL +@@ -3709,14 +3539,13 @@ struct tslist { + + #ifdef WLTDLS + /* different ops for manual end point */ +-#define TDLS_MANUAL_EP_CREATE 1 /* create manual dpt endpoint */ +-#define TDLS_MANUAL_EP_MODIFY 2 /* modify manual dpt endpoint */ +-#define TDLS_MANUAL_EP_DELETE 3 /* delete manual dpt endpoint */ ++#define TDLS_MANUAL_EP_CREATE 1 /* create manual dpt endpoint */ ++#define TDLS_MANUAL_EP_MODIFY 2 /* modify manual dpt endpoint */ ++#define TDLS_MANUAL_EP_DELETE 3 /* delete manual dpt endpoint */ + #define TDLS_MANUAL_EP_PM 4 /* put dpt endpoint in PM mode */ + #define TDLS_MANUAL_EP_WAKE 5 /* wake up dpt endpoint from PM */ + #define TDLS_MANUAL_EP_DISCOVERY 6 /* discover if endpoint is TDLS capable */ + #define TDLS_MANUAL_EP_CHSW 7 /* channel switch */ +-#define TDLS_MANUAL_EP_WFD_TPQ 8 /* WiFi-Display Tunneled Probe reQuest */ + + /* structure for tdls iovars */ + typedef struct tdls_iovar { +@@ -3727,16 +3556,14 @@ typedef struct tdls_iovar { + } tdls_iovar_t; + + /* modes */ +-#define TDLS_WFD_IE_TX 0 +-#define TDLS_WFD_IE_RX 1 +-#define TDLS_WFD_PROBE_IE_TX 2 +-#define TDLS_WFD_PROBE_IE_RX 3 +-#define TDLS_WFD_IE_SIZE 512 ++#define TDLS_WFD_IE_TX 0 ++#define TDLS_WFD_IE_RX 1 ++#define TDLS_WFD_IE_SIZE 255 + /* structure for tdls wfd ie */ + typedef struct tdls_wfd_ie_iovar { + struct ether_addr ea; /* Station address */ + uint8 mode; +- uint16 length; ++ uint8 length; + uint8 data[TDLS_WFD_IE_SIZE]; + } tdls_wfd_ie_iovar_t; + #endif /* WLTDLS */ +@@ -3799,11 +3626,11 @@ typedef struct wme_max_bandwidth { + + /* Software feature flag defines used by wlfeatureflag */ + #ifdef WLAFTERBURNER +-#define WL_SWFL_ABBFL 0x0001 /* Allow Afterburner on systems w/o hardware BFL */ +-#define WL_SWFL_ABENCORE 0x0002 /* Allow AB on non-4318E chips */ ++#define WL_SWFL_ABBFL 0x0001 /* Allow Afterburner on systems w/o hardware BFL */ ++#define WL_SWFL_ABENCORE 0x0002 /* Allow AB on non-4318E chips */ + #endif /* WLAFTERBURNER */ + #define WL_SWFL_NOHWRADIO 0x0004 +-#define WL_SWFL_FLOWCONTROL 0x0008 /* Enable backpressure to OS stack */ ++#define WL_SWFL_FLOWCONTROL 0x0008 /* Enable backpressure to OS stack */ + #define WL_SWFL_WLBSSSORT 0x0010 /* Per-port supports sorting of BSS */ + + #define WL_LIFETIME_MAX 0xFFFF /* Max value in ms */ +@@ -3868,13 +3695,11 @@ enum { + #define ENABLE_ADAPTSCAN_BIT 6 + #define IMMEDIATE_EVENT_BIT 8 + #define SUPPRESS_SSID_BIT 9 +-#define ENABLE_NET_OFFLOAD_BIT 10 +-/* report found/lost events for SSID and BSSID networks seperately */ +-#define REPORT_SEPERATELY_BIT 11 ++#define ENABLE_NET_OFFLOAD_BIT 10 + + #define SORT_CRITERIA_MASK 0x0001 +-#define AUTO_NET_SWITCH_MASK 0x0002 +-#define ENABLE_BKGRD_SCAN_MASK 0x0004 ++#define AUTO_NET_SWITCH_MASK 0x0002 ++#define ENABLE_BKGRD_SCAN_MASK 0x0004 + #define IMMEDIATE_SCAN_MASK 0x0008 + #define AUTO_CONNECT_MASK 0x0010 + +@@ -3883,10 +3708,8 @@ enum { + #define IMMEDIATE_EVENT_MASK 0x0100 + #define SUPPRESS_SSID_MASK 0x0200 + #define ENABLE_NET_OFFLOAD_MASK 0x0400 +-/* report found/lost events for SSID and BSSID networks seperately */ +-#define REPORT_SEPERATELY_MASK 0x0800 + +-#define PFN_VERSION 2 ++#define PFN_VERSION 2 + #define PFN_SCANRESULT_VERSION 1 + #define MAX_PFN_LIST_COUNT 16 + +@@ -3896,10 +3719,7 @@ enum { + #define DEFAULT_BESTN 2 + #define DEFAULT_MSCAN 0 + #define DEFAULT_REPEAT 10 +-#define DEFAULT_EXP 2 +- +-#define PFN_PARTIAL_SCAN_BIT 0 +-#define PFN_PARTIAL_SCAN_MASK 1 ++#define DEFAULT_EXP 2 + + /* PFN network info structure */ + typedef struct wl_pfn_subnet_info { +@@ -3915,22 +3735,6 @@ typedef struct wl_pfn_net_info { + uint16 timestamp; /* age in seconds */ + } wl_pfn_net_info_t; + +-typedef struct wl_pfn_lnet_info { +- wl_pfn_subnet_info_t pfnsubnet; /* BSSID + channel + SSID len + SSID */ +- uint16 flags; /* partial scan, etc */ +- int16 RSSI; /* receive signal strength (in dBm) */ +- uint32 timestamp; /* age in miliseconds */ +- uint16 rtt0; /* estimated distance to this AP in centimeters */ +- uint16 rtt1; /* standard deviation of the distance to this AP in centimeters */ +-} wl_pfn_lnet_info_t; +- +-typedef struct wl_pfn_lscanresults { +- uint32 version; +- uint32 status; +- uint32 count; +- wl_pfn_lnet_info_t netinfo[1]; +-} wl_pfn_lscanresults_t; +- + typedef struct wl_pfn_scanresults { + uint32 version; + uint32 status; +@@ -3943,127 +3747,57 @@ typedef struct wl_pfn_param { + int32 version; /* PNO parameters version */ + int32 scan_freq; /* Scan frequency */ + int32 lost_network_timeout; /* Timeout in sec. to declare +- * discovered network as lost +- */ ++ * discovered network as lost ++ */ + int16 flags; /* Bit field to control features +- * of PFN such as sort criteria auto +- * enable switch and background scan +- */ ++ * of PFN such as sort criteria auto ++ * enable switch and background scan ++ */ + int16 rssi_margin; /* Margin to avoid jitter for choosing a +- * PFN based on RSSI sort criteria +- */ +- uint8 bestn; /* number of best networks in each scan */ +- uint8 mscan; /* number of scans recorded */ +- uint8 repeat; /* Minimum number of scan intervals +- *before scan frequency changes in adaptive scan +- */ +- uint8 exp; /* Exponent of 2 for maximum scan interval */ +- int32 slow_freq; /* slow scan period */ ++ * PFN based on RSSI sort criteria ++ */ ++ uint8 bestn; /* number of best networks in each scan */ ++ uint8 mscan; /* number of scans recorded */ ++ uint8 repeat; /* Minimum number of scan intervals ++ *before scan frequency changes in adaptive scan ++ */ ++ uint8 exp; /* Exponent of 2 for maximum scan interval */ ++ int32 slow_freq; /* slow scan period */ + } wl_pfn_param_t; + + typedef struct wl_pfn_bssid { +- struct ether_addr macaddr; ++ struct ether_addr macaddr; + /* Bit4: suppress_lost, Bit3: suppress_found */ +- uint16 flags; ++ uint16 flags; + } wl_pfn_bssid_t; + #define WL_PFN_SUPPRESSFOUND_MASK 0x08 + #define WL_PFN_SUPPRESSLOST_MASK 0x10 +-#define WL_PFN_RSSI_MASK 0xff00 +-#define WL_PFN_RSSI_SHIFT 8 + + typedef struct wl_pfn_cfg { +- uint32 reporttype; +- int32 channel_num; +- uint16 channel_list[WL_NUMCHANNELS]; +- uint32 flags; ++ uint32 reporttype; ++ int32 channel_num; ++ uint16 channel_list[WL_NUMCHANNELS]; + } wl_pfn_cfg_t; +-#define WL_PFN_REPORT_ALLNET 0 +-#define WL_PFN_REPORT_SSIDNET 1 +-#define WL_PFN_REPORT_BSSIDNET 2 +- +-#define WL_PFN_CFG_FLAGS_PROHIBITED 0x00000001 /* Accept and use prohibited channels */ +-#define WL_PFN_CFG_FLAGS_RESERVED 0xfffffffe /* Remaining reserved for future use */ ++#define WL_PFN_REPORT_ALLNET 0 ++#define WL_PFN_REPORT_SSIDNET 1 ++#define WL_PFN_REPORT_BSSIDNET 2 + + typedef struct wl_pfn { +- wlc_ssid_t ssid; /* ssid name and its length */ +- int32 flags; /* bit2: hidden */ +- int32 infra; /* BSS Vs IBSS */ +- int32 auth; /* Open Vs Closed */ +- int32 wpa_auth; /* WPA type */ +- int32 wsec; /* wsec value */ ++ wlc_ssid_t ssid; /* ssid name and its length */ ++ int32 flags; /* bit2: hidden */ ++ int32 infra; /* BSS Vs IBSS */ ++ int32 auth; /* Open Vs Closed */ ++ int32 wpa_auth; /* WPA type */ ++ int32 wsec; /* wsec value */ + } wl_pfn_t; +-typedef struct wl_pfn_list { +- uint32 version; +- uint32 enabled; +- uint32 count; +- wl_pfn_t pfn[1]; +-} wl_pfn_list_t; +-#define WL_PFN_HIDDEN_BIT 2 ++#define WL_PFN_HIDDEN_BIT 2 + #define PNO_SCAN_MAX_FW 508*1000 /* max time scan time in msec */ + #define PNO_SCAN_MAX_FW_SEC PNO_SCAN_MAX_FW/1000 /* max time scan time in SEC */ +-#define PNO_SCAN_MIN_FW_SEC 10 /* min time scan time in SEC */ +-#define WL_PFN_HIDDEN_MASK 0x4 +-#ifndef BESTN_MAX +-#define BESTN_MAX 3 +-#endif +- +-#ifndef MSCAN_MAX +-#define MSCAN_MAX 90 +-#endif ++#define PNO_SCAN_MIN_FW_SEC 10 /* min time scan time in SEC */ ++#define WL_PFN_HIDDEN_MASK 0x4 + + #endif /* LINUX_POSTMOGRIFY_REMOVAL */ + +-/* Service discovery */ +-typedef struct { +- uint8 transaction_id; /* Transaction id */ +- uint8 protocol; /* Service protocol type */ +- uint16 query_len; /* Length of query */ +- uint16 response_len; /* Length of response */ +- uint8 qrbuf[1]; +-} wl_p2po_qr_t; +- +-typedef struct { +- uint16 period; /* extended listen period */ +- uint16 interval; /* extended listen interval */ +-} wl_p2po_listen_t; +- +-/* ANQP offload */ +- +-#define ANQPO_MAX_QUERY_SIZE 256 +-typedef struct { +- uint16 max_retransmit; /* -1 use default, max retransmit on no ACK from peer */ +- uint16 response_timeout; /* -1 use default, msec to wait for resp after tx packet */ +- uint16 max_comeback_delay; /* -1 use default, max comeback delay in resp else fail */ +- uint16 max_retries; /* -1 use default, max retries on failure */ +- uint16 query_len; /* length of ANQP query */ +- uint8 query_data[1]; /* ANQP encoded query (max ANQPO_MAX_QUERY_SIZE) */ +-} wl_anqpo_set_t; +- +-typedef struct { +- uint16 channel; /* channel of the peer */ +- struct ether_addr addr; /* addr of the peer */ +-} wl_anqpo_peer_t; +- +-#define ANQPO_MAX_PEER_LIST 64 +-typedef struct { +- uint16 count; /* number of peers in list */ +- wl_anqpo_peer_t peer[1]; /* max ANQPO_MAX_PEER_LIST */ +-} wl_anqpo_peer_list_t; +- +-#define ANQPO_MAX_IGNORE_SSID 64 +-typedef struct { +- bool is_clear; /* set to clear list (not used on GET) */ +- uint16 count; /* number of SSID in list */ +- wlc_ssid_t ssid[1]; /* max ANQPO_MAX_IGNORE_SSID */ +-} wl_anqpo_ignore_ssid_list_t; +- +-#define ANQPO_MAX_IGNORE_BSSID 64 +-typedef struct { +- bool is_clear; /* set to clear list (not used on GET) */ +- uint16 count; /* number of addr in list */ +- struct ether_addr bssid[1]; /* max ANQPO_MAX_IGNORE_BSSID */ +-} wl_anqpo_ignore_bssid_list_t; +- + /* TCP Checksum Offload defines */ + #define TOE_TX_CSUM_OL 0x00000001 + #define TOE_RX_CSUM_OL 0x00000002 +@@ -4116,7 +3850,7 @@ struct toe_ol_stats_t { + #define ARP_ERRTEST_REPLY_HOST 0x2 + + #define ARP_MULTIHOMING_MAX 8 /* Maximum local host IP addresses */ +-#define ND_MULTIHOMING_MAX 10 /* Maximum local host IP addresses */ ++#define ND_MULTIHOMING_MAX 8 /* Maximum local host IP addresses */ + + /* Arp offload statistic counts */ + struct arp_ol_stats_t { +@@ -4224,15 +3958,6 @@ typedef struct wl_pkt_filter_stats { + uint32 num_pkts_discarded; /* # packets discarded by dongle for all filters */ + } wl_pkt_filter_stats_t; + +-#define RSN_KCK_LENGTH 16 +-#define RSN_KEK_LENGTH 16 +-#define RSN_REPLAY_LEN 8 +-typedef struct _gtkrefresh { +- uchar KCK[RSN_KCK_LENGTH]; +- uchar KEK[RSN_KEK_LENGTH]; +- uchar ReplayCounter[RSN_REPLAY_LEN]; +-} gtk_keyinfo_t, *pgtk_keyinfo_t; +- + /* Sequential Commands ioctl */ + typedef struct wl_seq_cmd_ioctl { + uint32 cmd; /* common ioctl definition */ +@@ -4265,8 +3990,6 @@ typedef struct wl_seq_cmd_ioctl { + + #define WL_PKTENG_SYNCHRONOUS 0x100 /* synchronous flag */ + +-#define WL_PKTENG_MAXPKTSZ 16384 /* max pktsz limit for pkteng */ +- + typedef struct wl_pkteng { + uint32 flags; + uint32 delay; /* Inter-packet delay */ +@@ -4286,7 +4009,6 @@ typedef struct wl_pkteng_stats { + int32 rssi; /* RSSI */ + int32 snr; /* signal to noise ratio */ + uint16 rxpktcnt[NUM_80211_RATES+1]; +- uint8 rssi_qdb; /* qdB portion of the computed rssi */ + } wl_pkteng_stats_t; + + +@@ -4310,14 +4032,14 @@ typedef struct wl_pkteng_stats { + #define MAGIC_PKT_MINLEN 102 /* Magic pkt min length is 6 * 0xFF + 16 * ETHER_ADDR_LEN */ + + #define WOWL_PATTEN_TYPE_ARP (1 << 0) /* ARP offload Pattern */ +-#define WOWL_PATTEN_TYPE_NA (1 << 1) /* NA offload Pattern */ ++#define WOWL_PATTEN_TYPE_NA (1 << 1) /* NA offload Pattern */ + + typedef struct { + uint32 masksize; /* Size of the mask in #of bytes */ + uint32 offset; /* Offset to start looking for the packet in # of bytes */ +- uint32 patternoffset; /* Offset of start of pattern in the structure */ ++ uint32 patternoffset; /* Offset of start of pattern in the structure */ + uint32 patternsize; /* Size of the pattern itself in #of bytes */ +- uint32 id; /* id */ ++ uint32 id; /* id */ + uint32 reasonsize; /* Size of the wakeup reason code */ + uint32 flags; /* Flags to tell the pattern type and other properties */ + /* Mask follows the structure above */ +@@ -4451,37 +4173,6 @@ typedef struct { + uint32 queue_capacity; /* the maximum capacity of the queue */ + } pktq_log_counters_v01_t; + +-typedef struct { +- uint32 requested; /* packets requested to be stored */ +- uint32 stored; /* packets stored */ +- uint32 saved; /* packets saved, +- because a lowest priority queue has given away one packet +- */ +- uint32 selfsaved; /* packets saved, +- because an older packet from the same queue has been dropped +- */ +- uint32 full_dropped; /* packets dropped, +- because pktq is full with higher precedence packets +- */ +- uint32 dropped; /* packets dropped because pktq per that precedence is full */ +- uint32 sacrificed; /* packets dropped, +- in order to save one from a queue of a highest priority +- */ +- uint32 busy; /* packets droped because of hardware/transmission error */ +- uint32 retry; /* packets re-sent because they were not received */ +- uint32 ps_retry; /* packets retried again prior to moving power save mode */ +- uint32 retry_drop; /* packets finally dropped after retry limit */ +- uint32 max_avail; /* the high-water mark of the queue capacity for packets - +- goes to zero as queue fills +- */ +- uint32 max_used; /* the high-water mark of the queue utilisation for packets - +- increases with use ('inverse' of max_avail) +- */ +- uint32 queue_capacity; /* the maximum capacity of the queue */ +- uint32 rtsfail; /* count of rts attempts that failed to receive cts */ +- uint32 acked; /* count of packets sent (acked) successfully */ +-} pktq_log_counters_v02_t; +- + #define sacrified sacrificed + + typedef struct { +@@ -4490,21 +4181,12 @@ typedef struct { + char headings[1]; + } pktq_log_format_v01_t; + +-typedef struct { +- uint8 num_prec[WL_IOV_MAC_PARAM_LEN]; +- pktq_log_counters_v02_t counters[WL_IOV_MAC_PARAM_LEN][WL_IOV_PKTQ_LOG_PRECS]; +- uint32 throughput[WL_IOV_MAC_PARAM_LEN][WL_IOV_PKTQ_LOG_PRECS]; +- uint32 time_delta; +- char headings[1]; +-} pktq_log_format_v02_t; +- + + typedef struct { + uint32 version; + wl_iov_mac_params_t params; + union { + pktq_log_format_v01_t v01; +- pktq_log_format_v02_t v02; + } pktq_log; + } wl_iov_pktq_log_t; + +@@ -4662,21 +4344,6 @@ typedef struct { + #define VNDR_IE_IWAPID_FLAG 0x40 /* vendor IE in IW advertisement protocol ID field */ + #define VNDR_IE_CUSTOM_FLAG 0x100 /* allow custom IE id */ + +-#if defined(WLP2P) +-/* P2P Action Frames flags (spec ordered) */ +-#define VNDR_IE_GONREQ_FLAG 0x001000 +-#define VNDR_IE_GONRSP_FLAG 0x002000 +-#define VNDR_IE_GONCFM_FLAG 0x004000 +-#define VNDR_IE_INVREQ_FLAG 0x008000 +-#define VNDR_IE_INVRSP_FLAG 0x010000 +-#define VNDR_IE_DISREQ_FLAG 0x020000 +-#define VNDR_IE_DISRSP_FLAG 0x040000 +-#define VNDR_IE_PRDREQ_FLAG 0x080000 +-#define VNDR_IE_PRDRSP_FLAG 0x100000 +- +-#define VNDR_IE_P2PAF_SHIFT 12 +-#endif /* WLP2P */ +- + #define VNDR_IE_INFO_HDR_LEN (sizeof(uint32)) + + typedef BWL_PRE_PACKED_STRUCT struct { +@@ -4751,40 +4418,26 @@ typedef BWL_PRE_PACKED_STRUCT struct { + } BWL_POST_PACKED_STRUCT txfailinfo_t; + #endif /* WLMEDIA_TXFAILEVENT */ + +-typedef BWL_PRE_PACKED_STRUCT struct { +- uint32 flags; +- chanspec_t chanspec; /* txpwr report for this channel */ +- chanspec_t local_chanspec; /* channel on which we are associated */ +- uint8 local_max; /* local max according to the AP */ +- uint8 local_constraint; /* local constraint according to the AP */ +- int8 antgain[2]; /* Ant gain for each band - from SROM */ +- uint8 rf_cores; /* count of RF Cores being reported */ +- uint8 est_Pout[4]; /* Latest tx power out estimate per RF chain */ +- uint8 est_Pout_act[4]; /* Latest tx power out estimate per RF chain w/o adjustment */ +- uint8 est_Pout_cck; /* Latest CCK tx power out estimate */ +- uint8 tx_power_max[4]; /* Maximum target power among all rates */ +- uint tx_power_max_rate_ind[4]; /* Index of the rate with the max target power */ +- int8 clm_limits[WL_NUMRATES]; /* regulatory limits - 20, 40 or 80MHz */ +- int8 clm_limits_subchan1[WL_NUMRATES]; /* regulatory limits - 20in40 or 40in80 */ +- int8 clm_limits_subchan2[WL_NUMRATES]; /* regulatory limits - 20in80MHz */ +- int8 sar; /* SAR limit for display by wl executable */ +- int8 channel_bandwidth; /* 20, 40 or 80 MHz bandwidth? */ +- uint8 version; /* Version of the data format wlu <--> driver */ +- uint8 display_core; /* Displayed curpower core */ +- int8 target_offsets[4]; /* Target power offsets for current rate per core */ +- uint32 last_tx_ratespec; /* Ratespec for last transmition */ +- uint user_target; /* user limit */ +- uint32 board_limit_len; /* length of board limit buffer */ +- uint32 target_len; /* length of target power buffer */ +- int8 SARLIMIT[MAX_STREAMS_SUPPORTED]; +- uint8 pprdata[1]; /* ppr serialization buffer */ +-} BWL_POST_PACKED_STRUCT tx_pwr_rpt_t; +- + #endif /* LINUX_POSTMOGRIFY_REMOVAL */ + + /* no strict structure packing */ + #include + ++#ifdef BCMWAPI_WAI ++#define IV_LEN 16 /* XXX, same as SMS4_WPI_PN_LEN */ ++struct wapi_sta_msg_t ++{ ++ uint16 msg_type; ++ uint16 datalen; ++ uint8 vap_mac[6]; ++ uint8 reserve_data1[2]; ++ uint8 sta_mac[6]; ++ uint8 reserve_data2[2]; ++ uint8 gsn[IV_LEN]; ++ uint8 wie[256]; ++}; ++#endif /* BCMWAPI_WAI */ ++ + #ifndef LINUX_POSTMOGRIFY_REMOVAL + /* Global ASSERT Logging */ + #define ASSERTLOG_CUR_VER 0x0100 +@@ -4818,12 +4471,10 @@ typedef struct assertlog_results { + + /* define for apcs reason code */ + #define APCS_INIT 0 +-#define APCS_IOCTL 1 +-#define APCS_CHANIM 2 ++#define APCS_IOCTL 1 ++#define APCS_CHANIM 2 + #define APCS_CSTIMER 3 + #define APCS_BTA 4 +-#define APCS_TXDLY 5 +-#define APCS_NONACSD 6 + + /* number of ACS record entries */ + #define CHANIM_ACS_RECORD 10 +@@ -5095,9 +4746,7 @@ typedef struct wl_nic_cnx { + uint8 SSID_len; + uint8 SSID[32]; + struct ether_addr abssid; +- uint16 beacon_interval; +- uint16 sync_threshold; +- uint16 beacon_wait_time; ++ uint8 join_period; + } wl_nic_cnx_t; + + /* opcode */ +@@ -5111,23 +4760,16 @@ typedef struct wl_nic_cnx { + typedef struct wl_nic_cfg { + uint8 version; + uint8 beacon_mode; ++ uint16 beacon_interval; + uint8 diluted_beacon_period; +- uint8 beacon_probability; +- uint8 num_awake_window_params; +- struct { +- uint8 channel_number; +- uint8 awake_window_length; +- uint8 repeat_EQC; +- } awake_window_params[3]; ++ uint8 repeat_EQC; + uint8 scan_length; + uint8 scan_interval; + uint8 scan_probability; ++ uint8 awake_window_length; ++ int8 TSF_correction; + uint8 ASID; + uint8 channel_usage_mode; +- uint8 CWmin_af; +- uint8 NIC_priority; +- uint8 NIC_data_ind; +- uint8 allowed_wakeup_delay; + } wl_nic_cfg_t; + + /* version */ +@@ -5149,6 +4791,7 @@ typedef struct wl_nic_frm { + } wl_nic_frm_t; + + /* type */ ++#define WL_NIC_FRM_MYNET 1 + #define WL_NIC_FRM_ACTION 2 + + /* i/f query */ +@@ -5161,17 +4804,8 @@ typedef struct wl_nic_ifq { + /* nic_dm iovar */ + typedef struct wl_nic_dm { + uint8 enab; +- uint8 rsvd; +- /* the following fields are valid when enabling... */ + chanspec_t chspec; +- uint8 DATA_priority; +- uint8 NIC_priority; + } wl_nic_dm_t; +- +-/* immediate scan request */ +-typedef struct wl_nic_isq { +- uint8 scan_length; +-} wl_nic_isq_t; + #endif /* WLNIC */ + + /* RFAWARE def */ +@@ -5316,13 +4950,6 @@ enum { + SPATIAL_MODE_MAX_IDX + }; + +-#define WLC_TXCORE_MAX 4 /* max number of txcore supports */ +-#define WLC_SUBBAND_MAX 4 /* max number of sub-band supports */ +-typedef struct { +- uint8 band2g[WLC_TXCORE_MAX]; +- uint8 band5g[WLC_SUBBAND_MAX][WLC_TXCORE_MAX]; +-} sar_limit_t; +- + /* IOVAR "mempool" parameter. Used to retrieve a list of memory pool statistics. */ + typedef struct wl_mempool_stats { + int num; /* Number of memory pools */ +@@ -5358,23 +4985,15 @@ typedef struct { + #define TRF_MGMT_MAX_PRIORITIES 3 + + #define TRF_MGMT_FLAG_ADD_DSCP 0x0001 /* Add DSCP to IP TOS field */ +-#define TRF_MGMT_FLAG_DISABLE_SHAPING 0x0002 /* Don't shape traffic */ +-#define TRF_MGMT_FLAG_MANAGE_LOCAL_TRAFFIC 0x0008 /* Manage traffic over our local subnet */ +-#define TRF_MGMT_FLAG_FILTER_ON_MACADDR 0x0010 /* filter on MAC address */ +-#define TRF_MGMT_FLAG_NO_RX 0x0020 /* do not apply fiters to rx packets */ +- +-#define TRF_FILTER_MAC_ADDR 0x0001 /* L2 filter use dst mac address for filtering */ +-#define TRF_FILTER_IP_ADDR 0x0002 /* L3 filter use ip ddress for filtering */ +-#define TRF_FILTER_L4 0x0004 /* L4 filter use tcp/udp for filtering */ +-#define TRF_FILTER_FAVORED 0x0010 /* Tag the packet FAVORED */ ++#define TRF_MGMT_FLAG_DISABLE_SHAPING 0x0002 /* Only support traffic clasification */ ++#define TRF_MGMT_FLAG_DISABLE_PRIORITY_TAGGING 0x0004 /* Don't override packet's priority */ + + /* Traffic management priority classes */ + typedef enum trf_mgmt_priority_class { +- trf_mgmt_priority_low = 0, /* Maps to 802.1p BK */ +- trf_mgmt_priority_medium = 1, /* Maps to 802.1p BE */ +- trf_mgmt_priority_high = 2, /* Maps to 802.1p VI */ +- trf_mgmt_priority_nochange = 3, /* do not update the priority */ +- trf_mgmt_priority_invalid = (trf_mgmt_priority_nochange + 1) ++ trf_mgmt_priority_low = 0, /* Maps to 802.1p BO */ ++ trf_mgmt_priority_medium = 1, /* Maps to 802.1p BE */ ++ trf_mgmt_priority_high = 2, /* Maps to 802.1p VI */ ++ trf_mgmt_priority_invalid = (trf_mgmt_priority_high + 1) + } trf_mgmt_priority_class_t; + + /* Traffic management configuration parameters */ +@@ -5456,163 +5075,5 @@ typedef struct powersel_params { + uint8 pwr_sel_exp_time; /* Time lapse for expiry of database */ + } powersel_params_t; + +-/* tx pkt delay statistics */ +-#define SCB_RETRY_SHORT_DEF 7 /* Default Short retry Limit */ +-#define WLPKTDLY_HIST_NBINS 16 /* number of bins used in the Delay histogram */ +- +-/* structure to store per-AC delay statistics */ +-typedef struct scb_delay_stats { +- uint32 txmpdu_lost; /* number of MPDUs lost */ +- uint32 txmpdu_cnt[SCB_RETRY_SHORT_DEF]; /* retry times histogram */ +- uint32 delay_sum[SCB_RETRY_SHORT_DEF]; /* cumulative packet latency */ +- uint32 delay_min; /* minimum packet latency observed */ +- uint32 delay_max; /* maximum packet latency observed */ +- uint32 delay_avg; /* packet latency average */ +- uint32 delay_hist[WLPKTDLY_HIST_NBINS]; /* delay histogram */ +-} scb_delay_stats_t; +- +-/* structure for txdelay event */ +-typedef struct txdelay_event { +- uint8 status; +- int rssi; +- chanim_stats_t chanim_stats; +- scb_delay_stats_t delay_stats[AC_COUNT]; +-} txdelay_event_t; +- +-/* structure for txdelay parameters */ +-typedef struct txdelay_params { +- uint16 ratio; /* Avg Txdelay Delta */ +- uint8 cnt; /* Sample cnt */ +- uint8 period; /* Sample period */ +- uint8 tune; /* Debug */ +-} txdelay_params_t; +- +-#define WL_RELMCAST_MAX_CLIENT 32 +-#define WL_RELMCAST_FLAG_INBLACKLIST 1 +-#define WL_RELMCAST_FLAG_ACTIVEACKER 2 +-#define WL_RELMCAST_FLAG_RELMCAST 4 +-#define WL_RELMCAST_MAX_TABLE_ENTRY 4 +- +-#define WL_RELMCAST_VER 1 +-#define WL_RELMCAST_INDEX_ACK_ALL 255 +-#define WL_RELMCAST_NUM_OF_MC_STREAMS 4 +-#define WL_RELMCAST_MAX_TRS_PER_GROUP 1 +-#define WL_RELMCAST_ACK_MCAST0 0x02 +-#define WL_RELMCAST_ACK_MCAST_ALL 0x01 +-#define WL_RELMCAST_ACTF_TIME_MIN 300 /* time in ms */ +-#define WL_RELMCAST_ACTF_TIME_MAX 20000 /* time in ms */ +- +-enum { +- RELMCAST_ENTRY_OP_DISABLE = 0, +- RELMCAST_ENTRY_OP_DELETE, +- RELMCAST_ENTRY_OP_ENABLE, +- RELMCAST_ENTRY_OP_ACK_ALL +-}; +- +-enum { +- WL_RELMCAST_MODE_RECEIVER = 0, +- WL_RELMCAST_MODE_TRANSMITTER, +- WL_RELMCAST_MODE_INITIATOR +-}; +- +-typedef struct wl_relmcast_client { +- uint8 flag; +- int16 rssi; +- struct ether_addr addr; +-} wl_relmcast_client_t; +- +-typedef struct wl_relmcast_st { +- uint8 ver; +- uint8 num; +- wl_relmcast_client_t clients[WL_RELMCAST_MAX_CLIENT]; +- uint16 err; +-} wl_relmcast_status_t; +- +-typedef struct wl_relmcast_entry { +- int8 flag; +- struct ether_addr addr; +-} wl_relmcast_entry_t; +- +-typedef struct wl_relmcast_entry_table { +- int8 index; +- int8 opcode; +- wl_relmcast_entry_t entry[WL_RELMCAST_MAX_TABLE_ENTRY]; +-} wl_relmcast_entry_table_t; +- +-typedef struct wl_tr_Info { +- struct ether_addr addr; +- uint32 timeVal; +- uint16 seq; +-} wl_tr_Info_t; +- +-typedef struct wl_mcGrpEntry { +- struct ether_addr mcaddr; +- struct ether_addr ar; +- wl_tr_Info_t trInfo[WL_RELMCAST_MAX_TRS_PER_GROUP]; +-} wl_mcGrpEntry_t; +- +-typedef struct wl_mcAckAllEntry { +- struct ether_addr ar; +- wl_tr_Info_t trInfo[WL_RELMCAST_NUM_OF_MC_STREAMS]; +-} wl_mcAckAllEntry_t; +- +-typedef struct wl_relmcast_globalMcTbl { +- uint8 activeMask; +- wl_mcAckAllEntry_t ackAll; +- wl_mcGrpEntry_t mcEntry[WL_RELMCAST_NUM_OF_MC_STREAMS]; +-} wl_relmcast_globalMcTbl_t; + #endif /* LINUX_POSTMOGRIFY_REMOVAL */ +- +-/* fbt_cap: FBT assoc / reassoc modes. */ +-#define WLC_FBT_CAP_DRV_4WAY_AND_REASSOC 1 /* Driver 4-way handshake & reassoc (WLFBT). */ +- +-typedef struct bcnreq { +- uint8 bcn_mode; +- int dur; +- int channel; +- struct ether_addr da; +- uint16 random_int; +- wlc_ssid_t ssid; +- uint16 reps; +-} bcnreq_t; +- +-typedef struct rrmreq { +- struct ether_addr da; +- uint8 reg; +- uint8 chan; +- uint16 random_int; +- uint16 dur; +- uint16 reps; +-} rrmreq_t; +- +-typedef struct framereq { +- struct ether_addr da; +- uint8 reg; +- uint8 chan; +- uint16 random_int; +- uint16 dur; +- struct ether_addr ta; +- uint16 reps; +-} framereq_t; +- +-typedef struct statreq { +- struct ether_addr da; +- struct ether_addr peer; +- uint16 random_int; +- uint16 dur; +- uint8 group_id; +- uint16 reps; +-} statreq_t; +- +-typedef struct wl_el_set_params_s { +- uint8 set; /* Set number */ +- uint32 size; /* Size to make/expand */ +-} wl_el_set_params_t; +- +-typedef struct wl_el_tag_params_s { +- uint16 tag; +- uint8 set; +- uint8 flags; +-} wl_el_tag_params_t; +- + #endif /* _wlioctl_h_ */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/Kconfig linux-sunxi-new/drivers/net/wireless/bcmdhd/Kconfig +--- linux-sunxi/drivers/net/wireless/bcmdhd/Kconfig 2014-01-27 01:30:30.100433249 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/Kconfig 2014-02-15 00:43:44.791014047 +0100 +@@ -1,33 +1,22 @@ + config BCMDHD + tristate "Broadcom 4329/30 wireless cards support" + depends on MMC ++ default n + ---help--- + This module adds support for wireless adapters based on + Broadcom 4329/30 chipset. + +- This driver uses the kernel's wireless extensions subsystem. +- +- If you choose to build a module, it'll be called dhd. Say M if +- unsure. +- +-config BCM4339 +- tristate "Broadcom 4339 wireless cards support" +- depends on BCMDHD +- ---help--- +- This module adds support for wireless adapters based on +- Broadcom 4339 chipset. +- + config BCMDHD_FW_PATH + depends on BCMDHD + string "Firmware path" +- default "/system/etc/firmware/fw_bcmdhd.bin" ++ default "/system/vendor/modules/fw_bcmxxxx.bin" + ---help--- + Path to the firmware file. + + config BCMDHD_NVRAM_PATH + depends on BCMDHD + string "NVRAM path" +- default "/system/etc/wifi/bcmdhd.cal" ++ default "/system/vendor/modules/nvram_apxxxx.txt" + ---help--- + Path to the calibration file. + +@@ -39,16 +28,18 @@ config BCMDHD_WEXT + help + Enables WEXT support + +-config DHD_USE_STATIC_BUF +- bool "Enable memory preallocation" ++choice ++ depends on BCMDHD ++ prompt "Interrupt type" ++config BCMDHD_OOB + depends on BCMDHD +- default n ++ bool "Out-of-Band Interrupt" + ---help--- +- Use memory preallocated in platform +- +-config DHD_USE_SCHED_SCAN +- bool "Use CFG80211 sched scan" +- depends on BCMDHD && CFG80211 +- default n ++ Interrupt through WL_HOST_WAKE. ++config BCMDHD_SDIO_IRQ ++ depends on BCMDHD ++ bool "In-Band Interrupt" ++ default y + ---help--- +- Use CFG80211 sched scan ++ Interrupt through SDIO DAT[1] ++endchoice +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/linux_osl.c linux-sunxi-new/drivers/net/wireless/bcmdhd/linux_osl.c +--- linux-sunxi/drivers/net/wireless/bcmdhd/linux_osl.c 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/linux_osl.c 2014-02-15 00:43:44.795014136 +0100 +@@ -1,7 +1,7 @@ + /* + * Linux OS Independent Layer + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -21,7 +21,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: linux_osl.c 412994 2013-07-17 12:38:03Z $ ++ * $Id: linux_osl.c 373382 2012-12-07 07:59:52Z $ + */ + + #define LINUX_PORT +@@ -36,7 +36,6 @@ + #include + + +- + #include + + #define PCI_CFG_RETRY 10 +@@ -101,29 +100,13 @@ struct osl_info { + uint magic; + void *pdev; + atomic_t malloced; +- atomic_t pktalloced; /* Number of allocated packet buffers */ + uint failed; + uint bustype; + bcm_mem_link_t *dbgmem_list; + spinlock_t dbgmem_lock; +-#ifdef BCMDBG_CTRACE +- spinlock_t ctrace_lock; +- struct list_head ctrace_list; +- int ctrace_num; +-#endif /* BCMDBG_CTRACE */ + spinlock_t pktalloc_lock; + }; + +-#define OSL_PKTTAG_CLEAR(p) \ +-do { \ +- struct sk_buff *s = (struct sk_buff *)(p); \ +- ASSERT(OSL_PKTTAG_SZ == 32); \ +- *(uint32 *)(&s->cb[0]) = 0; *(uint32 *)(&s->cb[4]) = 0; \ +- *(uint32 *)(&s->cb[8]) = 0; *(uint32 *)(&s->cb[12]) = 0; \ +- *(uint32 *)(&s->cb[16]) = 0; *(uint32 *)(&s->cb[20]) = 0; \ +- *(uint32 *)(&s->cb[24]) = 0; *(uint32 *)(&s->cb[28]) = 0; \ +-} while (0) +- + /* PCMCIA attribute space access macros */ + + /* Global ASSERT type flag */ +@@ -173,14 +156,15 @@ static int16 linuxbcmerrormap[] = + -ENODEV, /* BCME_NODEVICE */ + -EINVAL, /* BCME_NMODE_DISABLED */ + -ENODATA, /* BCME_NONRESIDENT */ +- -EINVAL, /* BCME_SCANREJECT */ +- -EINVAL, /* BCME_USAGE_ERROR */ +- -EIO, /* BCME_IOCTL_ERROR */ +- -EIO, /* BCME_SERIAL_PORT_ERR */ + + /* When an new error code is added to bcmutils.h, add os + * specific error translation here as well + */ ++/* check if BCME_LAST changed since the last time this function was updated */ ++#if BCME_LAST != -42 ++#error "You need to add a OS error translation in the linuxbcmerrormap \ ++ for new error code defined in bcmutils.h" ++#endif + }; + + /* translate bcmerrors into linux errors */ +@@ -202,14 +186,8 @@ osl_t * + osl_attach(void *pdev, uint bustype, bool pkttag) + { + osl_t *osh; +- gfp_t flags; + +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) +- flags = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL; +-#else +- flags = GFP_ATOMIC; +-#endif +- if (!(osh = kmalloc(sizeof(osl_t), flags))) ++ if (!(osh = kmalloc(sizeof(osl_t), GFP_ATOMIC))) + return osh; + + ASSERT(osh); +@@ -251,10 +229,6 @@ osl_attach(void *pdev, uint bustype, boo + if (!(bcm_static_buf = (bcm_static_buf_t *)dhd_os_prealloc(osh, 3, STATIC_BUF_SIZE+ + STATIC_BUF_TOTAL_LEN))) { + printk("can not alloc static buf!\n"); +- bcm_static_skb = NULL; +- ASSERT(osh->magic == OS_HANDLE_MAGIC); +- kfree(osh); +- return NULL; + } + else + printk("alloc static buf at %x!\n", (unsigned int)bcm_static_buf); +@@ -270,30 +244,16 @@ osl_attach(void *pdev, uint bustype, boo + void *skb_buff_ptr = 0; + bcm_static_skb = (bcm_static_pkt_t *)((char *)bcm_static_buf + 2048); + skb_buff_ptr = dhd_os_prealloc(osh, 4, 0); +- if (!skb_buff_ptr) { +- printk("cannot alloc static buf!\n"); +- bcm_static_buf = NULL; +- bcm_static_skb = NULL; +- ASSERT(osh->magic == OS_HANDLE_MAGIC); +- kfree(osh); +- return NULL; +- } + +- bcopy(skb_buff_ptr, bcm_static_skb, sizeof(struct sk_buff *) * ++ bcopy(skb_buff_ptr, bcm_static_skb, sizeof(struct sk_buff *)* + (STATIC_PKT_MAX_NUM * 2 + STATIC_PKT_4PAGE_NUM)); +- for (i = 0; i < STATIC_PKT_MAX_NUM * 2 + STATIC_PKT_4PAGE_NUM; i++) ++ for (i = 0; i < (STATIC_PKT_MAX_NUM * 2 + STATIC_PKT_4PAGE_NUM); i++) + bcm_static_skb->pkt_use[i] = 0; + + sema_init(&bcm_static_skb->osl_pkt_sem, 1); + } + #endif /* CONFIG_DHD_USE_STATIC_BUF */ + +-#ifdef BCMDBG_CTRACE +- spin_lock_init(&osh->ctrace_lock); +- INIT_LIST_HEAD(&osh->ctrace_list); +- osh->ctrace_num = 0; +-#endif /* BCMDBG_CTRACE */ +- + spin_lock_init(&(osh->pktalloc_lock)); + + return osh; +@@ -318,17 +278,13 @@ osl_detach(osl_t *osh) + kfree(osh); + } + +-static struct sk_buff *osl_alloc_skb(osl_t *osh, unsigned int len) ++static struct sk_buff *osl_alloc_skb(unsigned int len) + { +- struct sk_buff *skb; + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) +- gfp_t flags = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL; +- +- skb = __dev_alloc_skb(len, flags); ++ return __dev_alloc_skb(len, GFP_ATOMIC); + #else +- skb = dev_alloc_skb(len); +-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) */ +- return skb; ++ return dev_alloc_skb(len); ++#endif + } + + #ifdef CTFPOOL +@@ -364,7 +320,7 @@ osl_ctfpool_add(osl_t *osh) + } + + /* Allocate a new skb and add it to the ctfpool */ +- skb = osl_alloc_skb(osh, osh->ctfpool->obj_size); ++ skb = osl_alloc_skb(osh->ctfpool->obj_size); + if (skb == NULL) { + printf("%s: skb alloc of len %d failed\n", __FUNCTION__, + osh->ctfpool->obj_size); +@@ -411,15 +367,9 @@ osl_ctfpool_replenish(osl_t *osh, uint t + int32 + osl_ctfpool_init(osl_t *osh, uint numobj, uint size) + { +- gfp_t flags; +- +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) +- flags = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL; +-#else +- flags = GFP_ATOMIC; +-#endif +- osh->ctfpool = kzalloc(sizeof(ctfpool_t), flags); ++ osh->ctfpool = kmalloc(sizeof(ctfpool_t), GFP_ATOMIC); + ASSERT(osh->ctfpool); ++ bzero(osh->ctfpool, sizeof(ctfpool_t)); + + osh->ctfpool->max_obj = numobj; + osh->ctfpool->obj_size = size; +@@ -532,13 +482,9 @@ osl_pktfastget(osl_t *osh, uint len) + + /* Init skb struct */ + skb->next = skb->prev = NULL; +-#if defined(__ARM_ARCH_7A__) +- skb->data = skb->head + NET_SKB_PAD; +- skb->tail = skb->head + NET_SKB_PAD; +-#else + skb->data = skb->head + 16; + skb->tail = skb->head + 16; +-#endif /* __ARM_ARCH_7A__ */ ++ + skb->len = 0; + skb->cloned = 0; + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14) +@@ -546,9 +492,6 @@ osl_pktfastget(osl_t *osh, uint len) + #endif + atomic_set(&skb->users, 1); + +- PKTSETCLINK(skb, NULL); +- PKTCCLRATTR(skb); +- + return skb; + } + #endif /* CTFPOOL */ +@@ -560,30 +503,22 @@ osl_pktfastget(osl_t *osh, uint len) + struct sk_buff * BCMFASTPATH + osl_pkt_tonative(osl_t *osh, void *pkt) + { ++#ifndef WL_UMK + struct sk_buff *nskb; +-#ifdef BCMDBG_CTRACE +- struct sk_buff *nskb1, *nskb2; ++ unsigned long flags; + #endif + + if (osh->pub.pkttag) +- OSL_PKTTAG_CLEAR(pkt); ++ bzero((void*)((struct sk_buff *)pkt)->cb, OSL_PKTTAG_SZ); + ++#ifndef WL_UMK + /* Decrement the packet counter */ + for (nskb = (struct sk_buff *)pkt; nskb; nskb = nskb->next) { +- atomic_sub(PKTISCHAINED(nskb) ? PKTCCNT(nskb) : 1, &osh->pktalloced); +- +-#ifdef BCMDBG_CTRACE +- for (nskb1 = nskb; nskb1 != NULL; nskb1 = nskb2) { +- if (PKTISCHAINED(nskb1)) { +- nskb2 = PKTCLINK(nskb1); +- } +- else +- nskb2 = NULL; +- +- DEL_CTRACE(osh, nskb1); +- } +-#endif /* BCMDBG_CTRACE */ ++ spin_lock_irqsave(&osh->pktalloc_lock, flags); ++ osh->pub.pktalloced--; ++ spin_unlock_irqrestore(&osh->pktalloc_lock, flags); + } ++#endif /* WL_UMK */ + return (struct sk_buff *)pkt; + } + +@@ -591,67 +526,49 @@ osl_pkt_tonative(osl_t *osh, void *pkt) + * In the process, native packet is destroyed, there is no copying + * Also, a packettag is zeroed out + */ +-#ifdef BCMDBG_CTRACE +-void * BCMFASTPATH +-osl_pkt_frmnative(osl_t *osh, void *pkt, int line, char *file) +-#else + void * BCMFASTPATH + osl_pkt_frmnative(osl_t *osh, void *pkt) +-#endif /* BCMDBG_CTRACE */ + { ++#ifndef WL_UMK + struct sk_buff *nskb; +-#ifdef BCMDBG_CTRACE +- struct sk_buff *nskb1, *nskb2; ++ unsigned long flags; + #endif + + if (osh->pub.pkttag) +- OSL_PKTTAG_CLEAR(pkt); ++ bzero((void*)((struct sk_buff *)pkt)->cb, OSL_PKTTAG_SZ); + ++#ifndef WL_UMK + /* Increment the packet counter */ + for (nskb = (struct sk_buff *)pkt; nskb; nskb = nskb->next) { +- atomic_add(PKTISCHAINED(nskb) ? PKTCCNT(nskb) : 1, &osh->pktalloced); +- +-#ifdef BCMDBG_CTRACE +- for (nskb1 = nskb; nskb1 != NULL; nskb1 = nskb2) { +- if (PKTISCHAINED(nskb1)) { +- nskb2 = PKTCLINK(nskb1); +- } +- else +- nskb2 = NULL; +- +- ADD_CTRACE(osh, nskb1, file, line); +- } +-#endif /* BCMDBG_CTRACE */ ++ spin_lock_irqsave(&osh->pktalloc_lock, flags); ++ osh->pub.pktalloced++; ++ spin_unlock_irqrestore(&osh->pktalloc_lock, flags); + } ++#endif /* WL_UMK */ + return (void *)pkt; + } + + /* Return a new packet. zero out pkttag */ +-#ifdef BCMDBG_CTRACE +-void * BCMFASTPATH +-osl_pktget(osl_t *osh, uint len, int line, char *file) +-#else + void * BCMFASTPATH + osl_pktget(osl_t *osh, uint len) +-#endif /* BCMDBG_CTRACE */ + { + struct sk_buff *skb; ++ unsigned long flags; + + #ifdef CTFPOOL + /* Allocate from local pool */ + skb = osl_pktfastget(osh, len); +- if ((skb != NULL) || ((skb = osl_alloc_skb(osh, len)) != NULL)) { ++ if ((skb != NULL) || ((skb = osl_alloc_skb(len)) != NULL)) { + #else /* CTFPOOL */ +- if ((skb = osl_alloc_skb(osh, len))) { ++ if ((skb = osl_alloc_skb(len))) { + #endif /* CTFPOOL */ +- skb->tail += len; +- skb->len += len; ++ skb_put(skb, len); + skb->priority = 0; + +-#ifdef BCMDBG_CTRACE +- ADD_CTRACE(osh, skb, file, line); +-#endif +- atomic_inc(&osh->pktalloced); ++ ++ spin_lock_irqsave(&osh->pktalloc_lock, flags); ++ osh->pub.pktalloced++; ++ spin_unlock_irqrestore(&osh->pktalloc_lock, flags); + } + + return ((void*) skb); +@@ -674,17 +591,10 @@ osl_pktfastfree(osl_t *osh, struct sk_bu + + /* We only need to init the fields that we change */ + skb->dev = NULL; +-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) + skb->dst = NULL; +-#endif +- OSL_PKTTAG_CLEAR(skb); ++ memset(skb->cb, 0, sizeof(skb->cb)); + skb->ip_summed = 0; +- +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) +- skb_orphan(skb); +-#else + skb->destructor = NULL; +-#endif + + ctfpool = (ctfpool_t *)CTFPOOLPTR(osh, skb); + ASSERT(ctfpool != NULL); +@@ -707,12 +617,7 @@ void BCMFASTPATH + osl_pktfree(osl_t *osh, void *p, bool send) + { + struct sk_buff *skb, *nskb; +- +- if (osh == NULL) +- { +- printk("%s: osh == NULL \n", __FUNCTION__); +- return; +- } ++ unsigned long flags; + + skb = (struct sk_buff*) p; + +@@ -726,21 +631,16 @@ osl_pktfree(osl_t *osh, void *p, bool se + nskb = skb->next; + skb->next = NULL; + +-#ifdef BCMDBG_CTRACE +- DEL_CTRACE(osh, skb); +-#endif + + + #ifdef CTFPOOL +- if (PKTISFAST(osh, skb)) { +- if (atomic_read(&skb->users) == 1) +- smp_rmb(); +- else if (!atomic_dec_and_test(&skb->users)) +- goto next_skb; ++ if ((PKTISFAST(osh, skb)) && (atomic_read(&skb->users) == 1)) + osl_pktfastfree(osh, skb); +- } else +-#endif ++ else { ++#else /* CTFPOOL */ + { ++#endif /* CTFPOOL */ ++ + if (skb->destructor) + /* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if + * destructor exists +@@ -752,10 +652,9 @@ osl_pktfree(osl_t *osh, void *p, bool se + */ + dev_kfree_skb(skb); + } +-#ifdef CTFPOOL +-next_skb: +-#endif +- atomic_dec(&osh->pktalloced); ++ spin_lock_irqsave(&osh->pktalloc_lock, flags); ++ osh->pub.pktalloced--; ++ spin_unlock_irqrestore(&osh->pktalloc_lock, flags); + skb = nskb; + } + } +@@ -767,8 +666,10 @@ osl_pktget_static(osl_t *osh, uint len) + int i = 0; + struct sk_buff *skb; + ++ + if (len > DHD_SKB_MAX_BUFSIZE) { +- printk("%s: attempt to allocate huge packet (0x%x)\n", __FUNCTION__, len); ++ printk("osl_pktget_static: Do we really need this big skb??" ++ " len=%d\n", len); + return osl_pktget(osh, len); + } + +@@ -793,6 +694,7 @@ osl_pktget_static(osl_t *osh, uint len) + } + + if (len <= DHD_SKB_2PAGE_BUFSIZE) { ++ + for (i = 0; i < STATIC_PKT_MAX_NUM; i++) { + if (bcm_static_skb->pkt_use[i + STATIC_PKT_MAX_NUM] + == 0) +@@ -824,7 +726,7 @@ osl_pktget_static(osl_t *osh, uint len) + #endif + + up(&bcm_static_skb->osl_pkt_sem); +- printk("%s: all static pkt in use!\n", __FUNCTION__); ++ printk("osl_pktget_static: all static pkt in use!\n"); + return osl_pktget(osh, len); + } + +@@ -855,39 +757,18 @@ osl_pktfree_static(osl_t *osh, void *p, + } + #ifdef ENHANCED_STATIC_BUF + if (p == bcm_static_skb->skb_16k) { +- bcm_static_skb->pkt_use[STATIC_PKT_MAX_NUM * 2] = 0; ++ bcm_static_skb->pkt_use[STATIC_PKT_MAX_NUM*2] = 0; + up(&bcm_static_skb->osl_pkt_sem); + return; + } + #endif + up(&bcm_static_skb->osl_pkt_sem); ++ + osl_pktfree(osh, p, send); ++ return; + } + #endif /* CONFIG_DHD_USE_STATIC_BUF */ + +-int osh_pktpadtailroom(osl_t *osh, void* p, int pad) +-{ +- int err; +- int ntail; +- struct sk_buff* skb = (struct sk_buff*)p; +- +- ntail = skb->data_len + pad - (skb->end - skb->tail); +- if (likely(skb_cloned(skb) || ntail > 0)) { +- err = pskb_expand_head(skb, 0, ntail, GFP_ATOMIC); +- if (unlikely(err)) +- goto done; +- } +- +- err = skb_linearize(skb); +- if (unlikely(err)) +- goto done; +- +- memset(skb->data + skb->len, 0, pad); +- +-done: +- return err; +-} +- + uint32 + osl_pci_read_config(osl_t *osh, uint offset, uint size) + { +@@ -944,11 +825,7 @@ osl_pci_slot(osl_t *osh) + { + ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev); + +-#if defined(__ARM_ARCH_7A__) && LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35) +- return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn) + 1; +-#else + return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn); +-#endif + } + + /* return the pci device pointed by osh->pdev */ +@@ -981,7 +858,6 @@ void * + osl_malloc(osl_t *osh, uint size) + { + void *addr; +- gfp_t flags; + + /* only ASSERT if osh is defined */ + if (osh) +@@ -1021,12 +897,7 @@ osl_malloc(osl_t *osh, uint size) + original: + #endif /* CONFIG_DHD_USE_STATIC_BUF */ + +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) +- flags = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL; +-#else +- flags = GFP_ATOMIC; +-#endif +- if ((addr = kmalloc(size, flags)) == NULL) { ++ if ((addr = kmalloc(size, GFP_ATOMIC)) == NULL) { + if (osh) + osh->failed++; + return (NULL); +@@ -1093,7 +964,6 @@ osl_dma_consistent_align(void) + void* + osl_dma_alloc_consistent(osl_t *osh, uint size, uint16 align_bits, uint *alloced, ulong *pap) + { +- void *va; + uint16 align = (1 << align_bits); + ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); + +@@ -1101,14 +971,7 @@ osl_dma_alloc_consistent(osl_t *osh, uin + size += align; + *alloced = size; + +-#ifdef __ARM_ARCH_7A__ +- va = kmalloc(size, GFP_ATOMIC | __GFP_ZERO); +- if (va) +- *pap = (ulong)__virt_to_phys((ulong)va); +-#else +- va = pci_alloc_consistent(osh->pdev, size, (dma_addr_t*)pap); +-#endif +- return va; ++ return (pci_alloc_consistent(osh->pdev, size, (dma_addr_t*)pap)); + } + + void +@@ -1116,52 +979,16 @@ osl_dma_free_consistent(osl_t *osh, void + { + ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); + +-#ifdef __ARM_ARCH_7A__ +- kfree(va); +-#else + pci_free_consistent(osh->pdev, size, va, (dma_addr_t)pa); +-#endif + } + + uint BCMFASTPATH +-osl_dma_map(osl_t *osh, void *va, uint size, int direction, void *p, hnddma_seg_map_t *dmah) ++osl_dma_map(osl_t *osh, void *va, uint size, int direction) + { + int dir; + + ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); + dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE; +- +-#if defined(__ARM_ARCH_7A__) && defined(BCMDMASGLISTOSL) +- if (dmah != NULL) { +- int32 nsegs, i, totsegs = 0, totlen = 0; +- struct scatterlist *sg, _sg[MAX_DMA_SEGS * 2]; +- struct sk_buff *skb; +- for (skb = (struct sk_buff *)p; skb != NULL; skb = PKTNEXT(osh, skb)) { +- sg = &_sg[totsegs]; +- if (skb_is_nonlinear(skb)) { +- nsegs = skb_to_sgvec(skb, sg, 0, PKTLEN(osh, skb)); +- ASSERT((nsegs > 0) && (totsegs + nsegs <= MAX_DMA_SEGS)); +- pci_map_sg(osh->pdev, sg, nsegs, dir); +- } else { +- nsegs = 1; +- ASSERT(totsegs + nsegs <= MAX_DMA_SEGS); +- sg->page_link = 0; +- sg_set_buf(sg, PKTDATA(osh, skb), PKTLEN(osh, skb)); +- pci_map_single(osh->pdev, PKTDATA(osh, skb), PKTLEN(osh, skb), dir); +- } +- totsegs += nsegs; +- totlen += PKTLEN(osh, skb); +- } +- dmah->nsegs = totsegs; +- dmah->origsize = totlen; +- for (i = 0, sg = _sg; i < totsegs; i++, sg++) { +- dmah->segs[i].addr = sg_phys(sg); +- dmah->segs[i].length = sg->length; +- } +- return dmah->segs[0].addr; +- } +-#endif /* __ARM_ARCH_7A__ && BCMDMASGLISTOSL */ +- + return (pci_map_single(osh->pdev, va, size, dir)); + } + +@@ -1190,11 +1017,10 @@ osl_assert(const char *exp, const char * + if (!basename) + basename = file; + +-#ifdef BCMASSERT_LOG + snprintf(tempbuf, 64, "\"%s\": file \"%s\", line %d\n", + exp, basename, line); ++ + printk("%s", tempbuf); +-#endif /* BCMASSERT_LOG */ + + + } +@@ -1212,47 +1038,22 @@ osl_delay(uint usec) + } + } + +-void +-osl_sleep(uint ms) +-{ +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) +- if (ms < 20) +- usleep_range(ms*1000, ms*1000 + 1000); +- else +-#endif +- msleep(ms); +-} +- + + /* Clone a packet. + * The pkttag contents are NOT cloned. + */ +-#ifdef BCMDBG_CTRACE +-void * +-osl_pktdup(osl_t *osh, void *skb, int line, char *file) +-#else + void * + osl_pktdup(osl_t *osh, void *skb) +-#endif /* BCMDBG_CTRACE */ + { + void * p; +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)) +- gfp_t flags; +-#endif +- +- ASSERT(!PKTISCHAINED(skb)); ++ unsigned long irqflags; + + /* clear the CTFBUF flag if set and map the rest of the buffer + * before cloning. + */ + PKTCTFMAP(osh, skb); + +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) +- flags = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL; +- if ((p = pskb_copy((struct sk_buff *)skb, flags)) == NULL) +-#else + if ((p = skb_clone((struct sk_buff *)skb, GFP_ATOMIC)) == NULL) +-#endif + return NULL; + + #ifdef CTFPOOL +@@ -1273,83 +1074,17 @@ osl_pktdup(osl_t *osh, void *skb) + } + #endif /* CTFPOOL */ + +- /* Clear PKTC context */ +- PKTSETCLINK(p, NULL); +- PKTCCLRFLAGS(p); +- PKTCSETCNT(p, 1); +- PKTCSETLEN(p, PKTLEN(osh, skb)); +- + /* skb_clone copies skb->cb.. we don't want that */ + if (osh->pub.pkttag) +- OSL_PKTTAG_CLEAR(p); ++ bzero((void*)((struct sk_buff *)p)->cb, OSL_PKTTAG_SZ); + + /* Increment the packet counter */ +- atomic_inc(&osh->pktalloced); +-#ifdef BCMDBG_CTRACE +- ADD_CTRACE(osh, (struct sk_buff *)p, file, line); +-#endif ++ spin_lock_irqsave(&osh->pktalloc_lock, irqflags); ++ osh->pub.pktalloced++; ++ spin_unlock_irqrestore(&osh->pktalloc_lock, irqflags); + return (p); + } + +-#ifdef BCMDBG_CTRACE +-int osl_pkt_is_frmnative(osl_t *osh, struct sk_buff *pkt) +-{ +- unsigned long flags; +- struct sk_buff *skb; +- int ck = FALSE; +- +- spin_lock_irqsave(&osh->ctrace_lock, flags); +- +- list_for_each_entry(skb, &osh->ctrace_list, ctrace_list) { +- if (pkt == skb) { +- ck = TRUE; +- break; +- } +- } +- +- spin_unlock_irqrestore(&osh->ctrace_lock, flags); +- return ck; +-} +- +-void osl_ctrace_dump(osl_t *osh, struct bcmstrbuf *b) +-{ +- unsigned long flags; +- struct sk_buff *skb; +- int idx = 0; +- int i, j; +- +- spin_lock_irqsave(&osh->ctrace_lock, flags); +- +- if (b != NULL) +- bcm_bprintf(b, " Total %d sbk not free\n", osh->ctrace_num); +- else +- printk(" Total %d sbk not free\n", osh->ctrace_num); +- +- list_for_each_entry(skb, &osh->ctrace_list, ctrace_list) { +- if (b != NULL) +- bcm_bprintf(b, "[%d] skb %p:\n", ++idx, skb); +- else +- printk("[%d] skb %p:\n", ++idx, skb); +- +- for (i = 0; i < skb->ctrace_count; i++) { +- j = (skb->ctrace_start + i) % CTRACE_NUM; +- if (b != NULL) +- bcm_bprintf(b, " [%s(%d)]\n", skb->func[j], skb->line[j]); +- else +- printk(" [%s(%d)]\n", skb->func[j], skb->line[j]); +- } +- if (b != NULL) +- bcm_bprintf(b, "\n"); +- else +- printk("\n"); +- } +- +- spin_unlock_irqrestore(&osh->ctrace_lock, flags); +- +- return; +-} +-#endif /* BCMDBG_CTRACE */ +- + + /* + * OSLREGOPS specifies the use of osl_XXX routines to be used for register access +@@ -1359,12 +1094,6 @@ void osl_ctrace_dump(osl_t *osh, struct + * BINOSL selects the slightly slower function-call-based binary compatible osl. + */ + +-uint +-osl_pktalloced(osl_t *osh) +-{ +- return (atomic_read(&osh->pktalloced)); +-} +- + /* Linux Kernel: File Operations: start */ + void * + osl_os_open_image(char *filename) +@@ -1406,21 +1135,4 @@ osl_os_close_image(void *image) + if (image) + filp_close((struct file *)image, NULL); + } +- +-int +-osl_os_image_size(void *image) +-{ +- int len = 0, curroffset; +- +- if (image) { +- /* store the current offset */ +- curroffset = generic_file_llseek(image, 0, 1); +- /* goto end of file to get length */ +- len = generic_file_llseek(image, 0, 2); +- /* restore back the offset */ +- generic_file_llseek(image, curroffset, 0); +- } +- return len; +-} +- + /* Linux Kernel: File Operations: end */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/Makefile linux-sunxi-new/drivers/net/wireless/bcmdhd/Makefile +--- linux-sunxi/drivers/net/wireless/bcmdhd/Makefile 2014-01-27 01:30:30.101433269 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/Makefile 2014-02-15 00:43:44.792014069 +0100 +@@ -1,36 +1,42 @@ + # bcmdhd +-# +-# +-# +-# +-# +- +-DHDCFLAGS = -Wall -Wstrict-prototypes -Dlinux -DBCMDRIVER \ ++DHDCFLAGS = -Wall -Wstrict-prototypes -Dlinux -DBCMDRIVER \ + -DBCMDONGLEHOST -DUNRELEASEDCHIP -DBCMDMA32 -DBCMFILEIMAGE \ +- -DDHDTHREAD -DDHD_DEBUG -DSDTEST -DBDC \ ++ -DDHDTHREAD -DDHD_DEBUG -DSDTEST -DBDC -DTOE \ + -DDHD_BCMEVENTS -DSHOW_EVENTS -DPROP_TXSTATUS -DBCMDBG \ +- -DCUSTOMER_HW2 -DOOB_INTR_ONLY -DHW_OOB \ + -DMMC_SDIO_ABORT -DBCMSDIO -DBCMLXSDMMC -DBCMPLATFORM_BUS -DWLP2P \ + -DWIFI_ACT_FRAME -DARP_OFFLOAD_SUPPORT \ +- -DKEEP_ALIVE -DGET_CUSTOM_MAC_ENABLE -DPKT_FILTER_SUPPORT \ ++ -DKEEP_ALIVE -DPKT_FILTER_SUPPORT \ + -DEMBEDDED_PLATFORM -DENABLE_INSMOD_NO_FW_LOAD -DPNO_SUPPORT \ +- -DDHD_USE_IDLECOUNT -DSET_RANDOM_MAC_SOFTAP -DROAM_ENABLE -DVSDB \ +- -DWL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST \ +- -DESCAN_RESULT_PATCH -DSDIO_CRC_ERROR_FIX \ +- -DDHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT -DRXFRAME_THREAD \ +- -DSUPPORT_PM2_ONLY -DWLTDLS \ +- -DMIRACAST_AMPDU_SIZE=8 \ +- -Idrivers/net/wireless/bcmdhd -Idrivers/net/wireless/bcmdhd/include \ +- -Idrivers/net/wireless/bcmdhd/common/include ++ -DDHD_USE_IDLECOUNT -DSET_RANDOM_MAC_SOFTAP -DVSDB \ ++ -DWL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST -DSDIO_CRC_ERROR_FIX \ ++ -DESCAN_RESULT_PATCH -DHT40_GO -DPASS_ARP_PACKET -DSUPPORT_PM2_ONLY \ ++ -DDHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT -DAMPDU_HOSTREORDER \ ++ -DDISABLE_FW_ROAM_SUSPEND -DDISABLE_BUILTIN_ROAM \ ++ -DCUSTOM_SDIO_F2_BLKSIZE=128 -DWL_SDO -DWL_SUPPORT_BACKPORTED_KPATCHES\ ++ -Idrivers/net/wireless/bcmdhd -Idrivers/net/wireless/bcmdhd/include + + DHDOFILES = aiutils.o bcmsdh_sdmmc_linux.o dhd_linux.o siutils.o bcmutils.o \ + dhd_linux_sched.o dhd_sdio.o bcmwifi_channels.o bcmevent.o hndpmu.o \ +- bcmsdh.o dhd_cdc.o bcmsdh_linux.o dhd_common.o dhd_wlfc.o dhd_ip.o \ +- linux_osl.o bcmsdh_sdmmc.o dhd_custom_gpio.o sbutils.o wldev_common.o \ +- wl_android.o dhd_pno.o ++ bcmsdh.o dhd_cdc.o bcmsdh_linux.o dhd_common.o linux_osl.o \ ++ bcmsdh_sdmmc.o dhd_custom_gpio.o sbutils.o wldev_common.o wl_android.o + + obj-$(CONFIG_BCMDHD) += bcmdhd.o + bcmdhd-objs += $(DHDOFILES) ++ ++DHDOFILES += dhd_gpio.o ++DHDCFLAGS += -DCUSTOMER_HW ++#DHDCFLAGS += -DBCMWAPI_WPI -DBCMWAPI_WAI ++ ++ifeq ($(CONFIG_BCMDHD_OOB),y) ++DHDCFLAGS += -DOOB_INTR_ONLY -DHW_OOB -DCUSTOMER_OOB ++else ++DHDCFLAGS += -DSDIO_ISR_THREAD ++endif ++ ++ifeq ($(CONFIG_BCMDHD_AG),y) ++ DHDCFLAGS += -DBAND_AG ++endif ++ + ifneq ($(CONFIG_WIRELESS_EXT),) + bcmdhd-objs += wl_iw.o + DHDCFLAGS += -DSOFTAP -DWL_WIRELESS_EXT -DUSE_IW +@@ -38,11 +44,10 @@ endif + ifneq ($(CONFIG_CFG80211),) + bcmdhd-objs += wl_cfg80211.o wl_cfgp2p.o wl_linux_mon.o dhd_cfg80211.o + DHDCFLAGS += -DWL_CFG80211 -DWL_CFG80211_STA_EVENT -DWL_ENABLE_P2P_IF +-DHDCFLAGS += -DWL_IFACE_COMB_NUM_CHANNELS +-DHDCFLAGS += -DCUSTOM_ROAM_TRIGGER_SETTING=-75 +-DHDCFLAGS += -DCUSTOM_ROAM_DELTA_SETTING=10 ++DHDCFLAGS += -DCUSTOM_ROAM_TRIGGER_SETTING=-65 ++DHDCFLAGS += -DCUSTOM_ROAM_DELTA_SETTING=15 + DHDCFLAGS += -DCUSTOM_KEEP_ALIVE_SETTING=28000 +-DHDCFLAGS += -DCUSTOM_PNO_EVENT_LOCK_xTIME=10 ++DHDCFLAGS += -DCUSTOM_PNO_EVENT_LOCK_xTIME=7 + endif + ifneq ($(CONFIG_DHD_USE_SCHED_SCAN),) + DHDCFLAGS += -DWL_SCHED_SCAN +@@ -51,28 +56,3 @@ EXTRA_CFLAGS = $(DHDCFLAGS) + ifeq ($(CONFIG_BCMDHD),m) + EXTRA_LDFLAGS += --strip-debug + endif +- +-DHDCFLAGS += -DCUSTOM_TDLS_RSSI_THRESHOLD_HIGH=-60 +-DHDCFLAGS += -DCUSTOM_TDLS_RSSI_THRESHOLD_LOW=-70 +-DHDCFLAGS += -DCUSTOM_TDLS_IDLE_MODE_SETTING=40000 +- +-######################### +-# Chip dependent feature +-######################### +-ifneq ($(CONFIG_BCM4339),) +-DHDCFLAGS += -DCUSTOM_GLOM_SETTING=8 -DCUSTOM_RXCHAIN=1 +-DHDCFLAGS += -DUSE_DYNAMIC_F2_BLKSIZE -DDYNAMIC_F2_BLKSIZE_FOR_NONLEGACY=128 +-DHDCFLAGS += -DBCMSDIOH_TXGLOM -DCUSTOM_TXGLOM=1 -DBCMSDIOH_TXGLOM_HIGHSPEED +-DHDCFLAGS += -DCUSTOM_SDIO_F2_BLKSIZE=512 +-DHDCFLAGS += -DDHDTCPACK_SUPPRESS +-DHDCFLAGS += -DUSE_WL_TXBF +-DHDCFLAGS += -DUSE_WL_FRAMEBURST +-DHDCFLAGS += -DCUSTOM_AMPDU_BA_WSIZE=32 +-DHDCFLAGS += -DPROP_TXSTATUS_VSDB +-DHDCFLAGS += -DCUSTOM_MAX_TXGLOM_SIZE=32 +-DHDCFLAGS += -DREPEAT_READFRAME +-DHDCFLAGS += -DROAM_AP_ENV_DETECTION +-DHDCFLAGS += -DWL11U +-else +-DHDCFLAGS += -DCUSTOM_SDIO_F2_BLKSIZE=128 +-endif +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/sbutils.c linux-sunxi-new/drivers/net/wireless/bcmdhd/sbutils.c +--- linux-sunxi/drivers/net/wireless/bcmdhd/sbutils.c 2014-01-27 01:30:30.108433411 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/sbutils.c 2014-02-15 00:43:44.795014136 +0100 +@@ -2,7 +2,7 @@ + * Misc utility routines for accessing chip-specific features + * of the SiliconBackplane-based Broadcom chips. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -22,7 +22,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: sbutils.c 379512 2013-01-17 22:49:08Z $ ++ * $Id: sbutils.c 310902 2012-01-26 19:45:33Z $ + */ + + #include +@@ -510,11 +510,10 @@ _sb_scan(si_info_t *sii, uint32 sba, voi + uint32 ccrev = sb_corerev(&sii->pub); + + /* determine numcores - this is the total # cores in the chip */ +- if (((ccrev == 4) || (ccrev >= 6))) { +- ASSERT(cc); ++ if (((ccrev == 4) || (ccrev >= 6))) + numcores = (R_REG(sii->osh, &cc->chipid) & CID_CC_MASK) >> + CID_CC_SHIFT; +- } else { ++ else { + /* Older chips */ + uint chip = CHIPID(sii->pub.chip); + +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/siutils.c linux-sunxi-new/drivers/net/wireless/bcmdhd/siutils.c +--- linux-sunxi/drivers/net/wireless/bcmdhd/siutils.c 2014-01-27 01:30:30.100433249 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/siutils.c 2014-02-15 00:43:44.791014047 +0100 +@@ -2,7 +2,7 @@ + * Misc utility routines for accessing chip-specific features + * of the SiliconBackplane-based Broadcom chips. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -22,7 +22,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: siutils.c 414368 2013-07-24 15:00:23Z $ ++ * $Id: siutils.c 347632 2012-07-27 11:00:35Z $ + */ + + #include +@@ -45,7 +45,6 @@ + #include + #include + +- + #include "siutils_priv.h" + + /* local prototypes */ +@@ -110,7 +109,6 @@ si_kattach(osl_t *osh) + void *regs = NULL; + regs = REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE); + +- ASSERT(osh); + if (si_doattach(&ksii, BCM4710_DEVICE_ID, osh, regs, + SI_BUS, NULL, + osh != SI_OSH ? &ksii.vars : NULL, +@@ -318,8 +316,7 @@ si_doattach(si_info_t *sii, uint devid, + chipcregs_t *cc; + char *pvars = NULL; + uint origidx; +-#if !defined(_CFEZ_) || defined(CFG_WL) +-#endif ++ + ASSERT(GOODREGS(regs)); + + bzero((uchar*)sii, sizeof(si_info_t)); +@@ -372,13 +369,16 @@ si_doattach(si_info_t *sii, uint devid, + return NULL; + } + w = R_REG(osh, &cc->chipid); +- if ((w & 0xfffff) == 148277) w -= 65532; + sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT; + /* Might as wll fill in chip id rev & pkg */ + sih->chip = w & CID_ID_MASK; + sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT; + sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT; + ++#if defined(HW_OOB) ++ bcmsdh_config_hw_oob_intr(sdh, sih->chip); ++#endif ++ + if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && (sih->chiprev == 0) && + (sih->chippkg != BCM4329_289PIN_PKG_ID)) { + sih->chippkg = BCM4329_182PIN_PKG_ID; +@@ -389,12 +389,8 @@ si_doattach(si_info_t *sii, uint devid, + if (CHIPTYPE(sii->pub.socitype) == SOCI_SB) { + SI_MSG(("Found chip type SB (0x%08x)\n", w)); + sb_scan(&sii->pub, regs, devid); +- } else if ((CHIPTYPE(sii->pub.socitype) == SOCI_AI) || +- (CHIPTYPE(sii->pub.socitype) == SOCI_NAI)) { +- if (CHIPTYPE(sii->pub.socitype) == SOCI_AI) +- SI_MSG(("Found chip type AI (0x%08x)\n", w)); +- else +- SI_MSG(("Found chip type NAI (0x%08x)\n", w)); ++ } else if (CHIPTYPE(sii->pub.socitype) == SOCI_AI) { ++ SI_MSG(("Found chip type AI (0x%08x)\n", w)); + /* pass chipc address instead of original core base */ + ai_scan(&sii->pub, (void *)(uintptr)cc, devid); + } else if (CHIPTYPE(sii->pub.socitype) == SOCI_UBUS) { +@@ -417,7 +413,6 @@ si_doattach(si_info_t *sii, uint devid, + goto exit; + } + +-#if !defined(_CFEZ_) || defined(CFG_WL) + if (CHIPID(sih->chip) == BCM4322_CHIP_ID && (((sih->chipst & CST4322_SPROM_OTP_SEL_MASK) + >> CST4322_SPROM_OTP_SEL_SHIFT) == (CST4322_OTP_PRESENT | + CST4322_SPROM_PRESENT))) { +@@ -446,7 +441,6 @@ si_doattach(si_info_t *sii, uint devid, + if (bustype == PCI_BUS) { + + } +-#endif + + pvars = NULL; + BCM_REFERENCE(pvars); +@@ -565,7 +559,7 @@ si_intflag(si_t *sih) + + if (CHIPTYPE(sih->socitype) == SOCI_SB) + return sb_intflag(sih); +- else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) ++ else if (CHIPTYPE(sih->socitype) == SOCI_AI) + return R_REG(sii->osh, ((uint32 *)(uintptr) + (sii->oob_router + OOB_STATUSA))); + else { +@@ -579,7 +573,7 @@ si_flag(si_t *sih) + { + if (CHIPTYPE(sih->socitype) == SOCI_SB) + return sb_flag(sih); +- else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) ++ else if (CHIPTYPE(sih->socitype) == SOCI_AI) + return ai_flag(sih); + else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) + return ub_flag(sih); +@@ -589,23 +583,12 @@ si_flag(si_t *sih) + } + } + +-uint +-si_flag_alt(si_t *sih) +-{ +- if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) +- return ai_flag_alt(sih); +- else { +- ASSERT(0); +- return 0; +- } +-} +- + void + si_setint(si_t *sih, int siflag) + { + if (CHIPTYPE(sih->socitype) == SOCI_SB) + sb_setint(sih, siflag); +- else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) ++ else if (CHIPTYPE(sih->socitype) == SOCI_AI) + ai_setint(sih, siflag); + else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) + ub_setint(sih, siflag); +@@ -662,7 +645,7 @@ si_corevendor(si_t *sih) + { + if (CHIPTYPE(sih->socitype) == SOCI_SB) + return sb_corevendor(sih); +- else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) ++ else if (CHIPTYPE(sih->socitype) == SOCI_AI) + return ai_corevendor(sih); + else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) + return ub_corevendor(sih); +@@ -683,7 +666,7 @@ si_corerev(si_t *sih) + { + if (CHIPTYPE(sih->socitype) == SOCI_SB) + return sb_corerev(sih); +- else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) ++ else if (CHIPTYPE(sih->socitype) == SOCI_AI) + return ai_corerev(sih); + else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) + return ub_corerev(sih); +@@ -727,18 +710,6 @@ si_corelist(si_t *sih, uint coreid[]) + return (sii->numcores); + } + +-/* return current wrapper mapping */ +-void * +-si_wrapperregs(si_t *sih) +-{ +- si_info_t *sii; +- +- sii = SI_INFO(sih); +- ASSERT(GOODREGS(sii->curwrap)); +- +- return (sii->curwrap); +-} +- + /* return current register mapping */ + void * + si_coreregs(si_t *sih) +@@ -767,7 +738,7 @@ si_setcore(si_t *sih, uint coreid, uint + + if (CHIPTYPE(sih->socitype) == SOCI_SB) + return sb_setcoreidx(sih, idx); +- else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) ++ else if (CHIPTYPE(sih->socitype) == SOCI_AI) + return ai_setcoreidx(sih, idx); + else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) + return ub_setcoreidx(sih, idx); +@@ -782,7 +753,7 @@ si_setcoreidx(si_t *sih, uint coreidx) + { + if (CHIPTYPE(sih->socitype) == SOCI_SB) + return sb_setcoreidx(sih, coreidx); +- else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) ++ else if (CHIPTYPE(sih->socitype) == SOCI_AI) + return ai_setcoreidx(sih, coreidx); + else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) + return ub_setcoreidx(sih, coreidx); +@@ -839,7 +810,7 @@ si_numaddrspaces(si_t *sih) + { + if (CHIPTYPE(sih->socitype) == SOCI_SB) + return sb_numaddrspaces(sih); +- else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) ++ else if (CHIPTYPE(sih->socitype) == SOCI_AI) + return ai_numaddrspaces(sih); + else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) + return ub_numaddrspaces(sih); +@@ -854,7 +825,7 @@ si_addrspace(si_t *sih, uint asidx) + { + if (CHIPTYPE(sih->socitype) == SOCI_SB) + return sb_addrspace(sih, asidx); +- else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) ++ else if (CHIPTYPE(sih->socitype) == SOCI_AI) + return ai_addrspace(sih, asidx); + else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) + return ub_addrspace(sih, asidx); +@@ -869,7 +840,7 @@ si_addrspacesize(si_t *sih, uint asidx) + { + if (CHIPTYPE(sih->socitype) == SOCI_SB) + return sb_addrspacesize(sih, asidx); +- else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) ++ else if (CHIPTYPE(sih->socitype) == SOCI_AI) + return ai_addrspacesize(sih, asidx); + else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) + return ub_addrspacesize(sih, asidx); +@@ -883,7 +854,7 @@ void + si_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size) + { + /* Only supported for SOCI_AI */ +- if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) ++ if (CHIPTYPE(sih->socitype) == SOCI_AI) + ai_coreaddrspaceX(sih, asidx, addr, size); + else + *size = 0; +@@ -894,7 +865,7 @@ si_core_cflags(si_t *sih, uint32 mask, u + { + if (CHIPTYPE(sih->socitype) == SOCI_SB) + return sb_core_cflags(sih, mask, val); +- else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) ++ else if (CHIPTYPE(sih->socitype) == SOCI_AI) + return ai_core_cflags(sih, mask, val); + else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) + return ub_core_cflags(sih, mask, val); +@@ -909,7 +880,7 @@ si_core_cflags_wo(si_t *sih, uint32 mask + { + if (CHIPTYPE(sih->socitype) == SOCI_SB) + sb_core_cflags_wo(sih, mask, val); +- else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) ++ else if (CHIPTYPE(sih->socitype) == SOCI_AI) + ai_core_cflags_wo(sih, mask, val); + else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) + ub_core_cflags_wo(sih, mask, val); +@@ -922,7 +893,7 @@ si_core_sflags(si_t *sih, uint32 mask, u + { + if (CHIPTYPE(sih->socitype) == SOCI_SB) + return sb_core_sflags(sih, mask, val); +- else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) ++ else if (CHIPTYPE(sih->socitype) == SOCI_AI) + return ai_core_sflags(sih, mask, val); + else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) + return ub_core_sflags(sih, mask, val); +@@ -937,7 +908,7 @@ si_iscoreup(si_t *sih) + { + if (CHIPTYPE(sih->socitype) == SOCI_SB) + return sb_iscoreup(sih); +- else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) ++ else if (CHIPTYPE(sih->socitype) == SOCI_AI) + return ai_iscoreup(sih); + else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) + return ub_iscoreup(sih); +@@ -951,7 +922,7 @@ uint + si_wrapperreg(si_t *sih, uint32 offset, uint32 mask, uint32 val) + { + /* only for AI back plane chips */ +- if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) ++ if (CHIPTYPE(sih->socitype) == SOCI_AI) + return (ai_wrap_reg(sih, offset, mask, val)); + return 0; + } +@@ -961,7 +932,7 @@ si_corereg(si_t *sih, uint coreidx, uint + { + if (CHIPTYPE(sih->socitype) == SOCI_SB) + return sb_corereg(sih, coreidx, regoff, mask, val); +- else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) ++ else if (CHIPTYPE(sih->socitype) == SOCI_AI) + return ai_corereg(sih, coreidx, regoff, mask, val); + else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) + return ub_corereg(sih, coreidx, regoff, mask, val); +@@ -976,7 +947,7 @@ si_core_disable(si_t *sih, uint32 bits) + { + if (CHIPTYPE(sih->socitype) == SOCI_SB) + sb_core_disable(sih, bits); +- else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) ++ else if (CHIPTYPE(sih->socitype) == SOCI_AI) + ai_core_disable(sih, bits); + else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) + ub_core_disable(sih, bits); +@@ -987,7 +958,7 @@ si_core_reset(si_t *sih, uint32 bits, ui + { + if (CHIPTYPE(sih->socitype) == SOCI_SB) + sb_core_reset(sih, bits, resetbits); +- else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) ++ else if (CHIPTYPE(sih->socitype) == SOCI_AI) + ai_core_reset(sih, bits, resetbits); + else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) + ub_core_reset(sih, bits, resetbits); +@@ -1117,7 +1088,6 @@ si_clock_rate(uint32 pll_type, uint32 n, + } + + +- + /* set chip watchdog reset timer to fire in 'ticks' */ + void + si_watchdog(si_t *sih, uint ticks) +@@ -1126,7 +1096,6 @@ si_watchdog(si_t *sih, uint ticks) + + if (PMUCTL_ENAB(sih)) { + +-#if !defined(_CFEZ_) || defined(CFG_WL) + if ((CHIPID(sih->chip) == BCM4319_CHIP_ID) && + (CHIPREV(sih->chiprev) == 0) && (ticks != 0)) { + si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), ~0, 0x2); +@@ -1134,7 +1103,6 @@ si_watchdog(si_t *sih, uint ticks) + si_core_disable(sih, 1); + si_setcore(sih, CC_CORE_ID, 0); + } +-#endif + + nb = (sih->ccrev < 26) ? 16 : ((sih->ccrev >= 37) ? 32 : 24); + /* The mips compiler uses the sllv instruction, +@@ -1197,7 +1165,6 @@ si_slowclk_src(si_info_t *sii) + return (SCC_SS_XTAL); + } else if (sii->pub.ccrev < 10) { + cc = (chipcregs_t *)si_setcoreidx(&sii->pub, sii->curidx); +- ASSERT(cc); + return (R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_SS_MASK); + } else /* Insta-clock */ + return (SCC_SS_XTAL); +@@ -1297,8 +1264,6 @@ si_clkctl_init(si_t *sih) + + si_clkctl_setdelay(sii, (void *)(uintptr)cc); + +- OSL_DELAY(20000); +- + if (!fast) + si_setcoreidx(sih, origidx); + } +@@ -2086,7 +2051,6 @@ done: + } + + +-#if !defined(_CFEZ_) || defined(CFG_WL) + void + si_btcgpiowar(si_t *sih) + { +@@ -2283,7 +2247,6 @@ si_chipcontrl_epa4331_wowl(si_t *sih, bo + } + si_setcoreidx(sih, origidx); + } +-#endif + + uint + si_pll_reset(si_t *sih) +@@ -2318,12 +2281,6 @@ si_clk_pmu_htavail_set(si_t *sih, bool s + { + } + +-/* Re-enable synth_pwrsw resource in min_res_mask for 4313 */ +-void +-si_pmu_synth_pwrsw_4313_war(si_t *sih) +-{ +-} +- + /* WL/BT control for 4313 btcombo boards >= P250 */ + void + si_btcombo_p250_4313_war(si_t *sih) +@@ -2415,7 +2372,6 @@ si_is_sprom_available(si_t *sih) + sii = SI_INFO(sih); + origidx = sii->curidx; + cc = si_setcoreidx(sih, SI_CC_IDX); +- ASSERT(cc); + sromctrl = R_REG(sii->osh, &cc->sromcontrol); + si_setcoreidx(sih, origidx); + return (sromctrl & SRC_PRESENT); +@@ -2454,14 +2410,11 @@ si_is_sprom_available(si_t *sih) + return ((sih->chipst & CST43239_SPROM_MASK) && + !(sih->chipst & CST43239_SFLASH_MASK)); + case BCM4324_CHIP_ID: +- case BCM43242_CHIP_ID: + return ((sih->chipst & CST4324_SPROM_MASK) && + !(sih->chipst & CST4324_SFLASH_MASK)); + case BCM4335_CHIP_ID: + return ((sih->chipst & CST4335_SPROM_MASK) && + !(sih->chipst & CST4335_SFLASH_MASK)); +- case BCM4350_CHIP_ID: +- return (sih->chipst & CST4350_SPROM_PRESENT) != 0; + case BCM43131_CHIP_ID: + case BCM43217_CHIP_ID: + case BCM43227_CHIP_ID: +@@ -2515,20 +2468,3 @@ int si_set_sromctl(si_t *sih, uint32 val + return BCME_OK; + + } +- +-uint +-si_core_wrapperreg(si_t *sih, uint32 coreidx, uint32 offset, uint32 mask, uint32 val) +-{ +- uint origidx; +- uint ret_val; +- +- origidx = si_coreidx(sih); +- +- si_setcoreidx(sih, coreidx); +- +- ret_val = si_wrapperreg(sih, offset, mask, val); +- +- /* return to the original core */ +- si_setcoreidx(sih, origidx); +- return ret_val; +-} +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/siutils_priv.h linux-sunxi-new/drivers/net/wireless/bcmdhd/siutils_priv.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/siutils_priv.h 2014-01-27 01:30:30.100433249 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/siutils_priv.h 2014-02-15 00:43:44.791014047 +0100 +@@ -1,7 +1,7 @@ + /* + * Include file private to the SOC Interconnect support files. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -21,13 +21,13 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: siutils_priv.h 385510 2013-02-15 21:02:07Z $ ++ * $Id: siutils_priv.h 309193 2012-01-19 00:03:57Z $ + */ + + #ifndef _siutils_priv_h_ + #define _siutils_priv_h_ + +-#define SI_ERROR(args) ++#define SI_ERROR(args) printf args + + #define SI_MSG(args) + +@@ -146,7 +146,6 @@ typedef struct si_info { + #define ILP_DIV_5MHZ 0 /* ILP = 5 MHz */ + #define ILP_DIV_1MHZ 4 /* ILP = 1 MHz */ + +-/* Force fast clock for 4360b0 */ + #define PCI_FORCEHT(si) \ + (((PCIE_GEN1(si)) && (si->pub.chip == BCM4311_CHIP_ID) && ((si->pub.chiprev <= 1))) || \ + ((PCI(si) || PCIE_GEN1(si)) && (si->pub.chip == BCM4321_CHIP_ID)) || \ +@@ -204,7 +203,6 @@ extern si_t *ai_kattach(osl_t *osh); + extern void ai_scan(si_t *sih, void *regs, uint devid); + + extern uint ai_flag(si_t *sih); +-extern uint ai_flag_alt(si_t *sih); + extern void ai_setint(si_t *sih, int siflag); + extern uint ai_coreidx(si_t *sih); + extern uint ai_corevendor(si_t *sih); +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/uamp_api.h linux-sunxi-new/drivers/net/wireless/bcmdhd/uamp_api.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/uamp_api.h 2014-01-27 01:30:30.109433432 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/uamp_api.h 2014-02-15 00:43:44.795014136 +0100 +@@ -3,7 +3,7 @@ + * + * Description: Universal AMP API + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/wl_android.c linux-sunxi-new/drivers/net/wireless/bcmdhd/wl_android.c +--- linux-sunxi/drivers/net/wireless/bcmdhd/wl_android.c 2014-01-27 01:30:30.109433432 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/wl_android.c 2014-02-15 00:43:44.795014136 +0100 +@@ -1,7 +1,7 @@ + /* + * Linux cfg80211 driver - Android related functions + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -21,13 +21,11 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: wl_android.c 420671 2013-08-28 11:37:19Z $ ++ * $Id: wl_android.c 372668 2012-12-04 14:07:12Z $ + */ + + #include + #include +-#include +-#include + + #include + #include +@@ -37,9 +35,6 @@ + #include + #include + #include +-#ifdef PNO_SUPPORT +-#include +-#endif + #include + #ifdef WL_CFG80211 + #include +@@ -53,6 +48,44 @@ + #endif + #endif /* CONFIG_WIFI_CONTROL_FUNC */ + ++#ifndef WL_CFG80211 ++#define htod32(i) i ++#define htod16(i) i ++#define dtoh32(i) i ++#define dtoh16(i) i ++#define htodchanspec(i) i ++#define dtohchanspec(i) i ++#endif ++ ++/* message levels */ ++#define ANDROID_ERROR_LEVEL 0x0001 ++#define ANDROID_TRACE_LEVEL 0x0002 ++#define ANDROID_INFO_LEVEL 0x0004 ++ ++uint android_msg_level = ANDROID_ERROR_LEVEL; ++ ++#define ANDROID_ERROR(x) \ ++ do { \ ++ if (android_msg_level & ANDROID_ERROR_LEVEL) { \ ++ printk(KERN_ERR "ANDROID-ERROR) "); \ ++ printk x; \ ++ } \ ++ } while (0) ++#define ANDROID_TRACE(x) \ ++ do { \ ++ if (android_msg_level & ANDROID_TRACE_LEVEL) { \ ++ printk(KERN_ERR "ANDROID-TRACE) "); \ ++ printk x; \ ++ } \ ++ } while (0) ++#define ANDROID_INFO(x) \ ++ do { \ ++ if (android_msg_level & ANDROID_INFO_LEVEL) { \ ++ printk(KERN_ERR "ANDROID-INFO) "); \ ++ printk x; \ ++ } \ ++ } while (0) ++ + /* + * Android private command strings, PLEASE define new private commands here + * so they can be updated easily in the future (if needed) +@@ -80,14 +113,12 @@ + #define CMD_COUNTRY "COUNTRY" + #define CMD_P2P_SET_NOA "P2P_SET_NOA" + #if !defined WL_ENABLE_P2P_IF +-#define CMD_P2P_GET_NOA "P2P_GET_NOA" +-#endif /* WL_ENABLE_P2P_IF */ ++#define CMD_P2P_GET_NOA "P2P_GET_NOA" ++#endif + #define CMD_P2P_SD_OFFLOAD "P2P_SD_" + #define CMD_P2P_SET_PS "P2P_SET_PS" + #define CMD_SET_AP_WPS_P2P_IE "SET_AP_WPS_P2P_IE" + #define CMD_SETROAMMODE "SETROAMMODE" +-#define CMD_MIRACAST "MIRACAST" +- + + + /* CCX Private Commands */ +@@ -97,49 +128,34 @@ + #define CMD_PNOSETUP_SET "PNOSETUP " + #define CMD_PNOENABLE_SET "PNOFORCE" + #define CMD_PNODEBUG_SET "PNODEBUG" +-#define CMD_WLS_BATCHING "WLS_BATCHING" ++ ++#define PNO_TLV_PREFIX 'S' ++#define PNO_TLV_VERSION '1' ++#define PNO_TLV_SUBVERSION '2' ++#define PNO_TLV_RESERVED '0' ++#define PNO_TLV_TYPE_SSID_IE 'S' ++#define PNO_TLV_TYPE_TIME 'T' ++#define PNO_TLV_FREQ_REPEAT 'R' ++#define PNO_TLV_FREQ_EXPO_MAX 'M' ++ ++typedef struct cmd_tlv { ++ char prefix; ++ char version; ++ char subver; ++ char reserved; ++} cmd_tlv_t; + #endif /* PNO_SUPPORT */ + + #define CMD_OKC_SET_PMK "SET_PMK" + #define CMD_OKC_ENABLE "OKC_ENABLE" + + +-/* miracast related definition */ +-#define MIRACAST_MODE_OFF 0 +-#define MIRACAST_MODE_SOURCE 1 +-#define MIRACAST_MODE_SINK 2 +- +-#ifndef MIRACAST_AMPDU_SIZE +-#define MIRACAST_AMPDU_SIZE 8 +-#endif +- +-#ifndef MIRACAST_MCHAN_ALGO +-#define MIRACAST_MCHAN_ALGO 1 +-#endif +- +-#ifndef MIRACAST_MCHAN_BW +-#define MIRACAST_MCHAN_BW 25 +-#endif +- +-static LIST_HEAD(miracast_resume_list); +-static u8 miracast_cur_mode; +- +-struct io_cfg { +- s8 *iovar; +- s32 param; +- u32 ioctl; +- void *arg; +- u32 len; +- struct list_head list; +-}; +- + typedef struct android_wifi_priv_cmd { + char *buf; + int used_len; + int total_len; + } android_wifi_priv_cmd; + +- + /** + * Extern function declarations (TODO: move them to dhd_linux.h) + */ +@@ -149,7 +165,6 @@ int dhd_dev_init_ioctl(struct net_device + #ifdef WL_CFG80211 + int wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr); + int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command); +-int wl_cfg80211_get_ioctl_version(void); + #else + int wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr) + { return 0; } +@@ -159,24 +174,20 @@ int wl_cfg80211_get_p2p_noa(struct net_d + { return 0; } + int wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len) + { return 0; } +-#endif /* WK_CFG80211 */ ++#endif /* WL_CFG80211 */ ++ ++extern int dhd_os_check_wakelock(void *dhdp); + extern int dhd_os_check_if_up(void *dhdp); +-#ifdef BCMLXSDMMC + extern void *bcmsdh_get_drvdata(void); +-#endif /* BCMLXSDMMC */ +- +- +-#ifdef ENABLE_4335BT_WAR +-extern int bcm_bt_lock(int cookie); +-extern void bcm_bt_unlock(int cookie); +-static int lock_cookie_wifi = 'W' | 'i'<<8 | 'F'<<16 | 'i'<<24; /* cookie is "WiFi" */ +-#endif /* ENABLE_4335BT_WAR */ ++#if defined(PROP_TXSTATUS) && !defined(PROP_TXSTATUS_VSDB) ++extern int dhd_wlfc_init(dhd_pub_t *dhd); ++extern void dhd_wlfc_deinit(dhd_pub_t *dhd); ++#endif + + extern bool ap_fw_loaded; +-#if defined(CUSTOMER_HW2) + extern char iface_name[IFNAMSIZ]; +-#endif + ++#define WIFI_TURNOFF_DELAY 0 + /** + * Local (static) functions and variables + */ +@@ -203,7 +214,7 @@ static int wl_android_get_link_speed(str + /* Convert Kbps to Android Mbps */ + link_speed = link_speed / 1000; + bytes_written = snprintf(command, total_len, "LinkSpeed %d", link_speed); +- DHD_INFO(("%s: command result is %s\n", __FUNCTION__, command)); ++ ANDROID_INFO(("%s: command result is %s\n", __FUNCTION__, command)); + return bytes_written; + } + +@@ -217,18 +228,21 @@ static int wl_android_get_rssi(struct ne + error = wldev_get_rssi(net, &rssi); + if (error) + return -1; ++#if defined(RSSIOFFSET) ++ rssi = wl_update_rssi_offset(rssi); ++#endif + + error = wldev_get_ssid(net, &ssid); + if (error) + return -1; + if ((ssid.SSID_len == 0) || (ssid.SSID_len > DOT11_MAX_SSID_LEN)) { +- DHD_ERROR(("%s: wldev_get_ssid failed\n", __FUNCTION__)); ++ ANDROID_ERROR(("%s: wldev_get_ssid failed\n", __FUNCTION__)); + } else { + memcpy(command, ssid.SSID, ssid.SSID_len); + bytes_written = ssid.SSID_len; + } + bytes_written += snprintf(&command[bytes_written], total_len, " rssi %d", rssi); +- DHD_INFO(("%s: command result is %s (%d)\n", __FUNCTION__, command, bytes_written)); ++ ANDROID_INFO(("%s: command result is %s (%d)\n", __FUNCTION__, command, bytes_written)); + return bytes_written; + } + +@@ -238,19 +252,19 @@ static int wl_android_set_suspendopt(str + int ret_now; + int ret = 0; + +- suspend_flag = *(command + strlen(CMD_SETSUSPENDOPT) + 1) - '0'; ++ suspend_flag = *(command + strlen(CMD_SETSUSPENDOPT) + 1) - '0'; + +- if (suspend_flag != 0) +- suspend_flag = 1; +- ret_now = net_os_set_suspend_disable(dev, suspend_flag); +- +- if (ret_now != suspend_flag) { +- if (!(ret = net_os_set_suspend(dev, ret_now, 1))) +- DHD_INFO(("%s: Suspend Flag %d -> %d\n", +- __FUNCTION__, ret_now, suspend_flag)); +- else +- DHD_ERROR(("%s: failed %d\n", __FUNCTION__, ret)); +- } ++ if (suspend_flag != 0) ++ suspend_flag = 1; ++ ret_now = net_os_set_suspend_disable(dev, suspend_flag); ++ ++ if (ret_now != suspend_flag) { ++ if (!(ret = net_os_set_suspend(dev, ret_now, 1))) ++ ANDROID_INFO(("%s: Suspend Flag %d -> %d\n", ++ __FUNCTION__, ret_now, suspend_flag)); ++ else ++ ANDROID_ERROR(("%s: failed %d\n", __FUNCTION__, ret)); ++ } + return ret; + } + +@@ -262,15 +276,15 @@ static int wl_android_set_suspendmode(st + int suspend_flag; + + suspend_flag = *(command + strlen(CMD_SETSUSPENDMODE) + 1) - '0'; ++ + if (suspend_flag != 0) + suspend_flag = 1; + + if (!(ret = net_os_set_suspend(dev, suspend_flag, 0))) +- DHD_INFO(("%s: Suspend Mode %d\n", __FUNCTION__, suspend_flag)); ++ ANDROID_INFO(("%s: Suspend Mode %d\n",__FUNCTION__,suspend_flag)); + else +- DHD_ERROR(("%s: failed %d\n", __FUNCTION__, ret)); ++ ANDROID_ERROR(("%s: failed %d\n",__FUNCTION__,ret)); + #endif +- + return ret; + } + +@@ -287,118 +301,7 @@ static int wl_android_get_band(struct ne + return bytes_written; + } + +- +-#ifdef PNO_SUPPORT +-#define PARAM_SIZE 50 +-#define VALUE_SIZE 50 +-static int +-wls_parse_batching_cmd(struct net_device *dev, char *command, int total_len) +-{ +- int err = BCME_OK; +- uint i, tokens; +- char *pos, *pos2, *token, *token2, *delim; +- char param[PARAM_SIZE], value[VALUE_SIZE]; +- struct dhd_pno_batch_params batch_params; +- DHD_PNO(("%s: command=%s, len=%d\n", __FUNCTION__, command, total_len)); +- if (total_len < strlen(CMD_WLS_BATCHING)) { +- DHD_ERROR(("%s argument=%d less min size\n", __FUNCTION__, total_len)); +- err = BCME_ERROR; +- goto exit; +- } +- pos = command + strlen(CMD_WLS_BATCHING) + 1; +- memset(&batch_params, 0, sizeof(struct dhd_pno_batch_params)); +- +- if (!strncmp(pos, PNO_BATCHING_SET, strlen(PNO_BATCHING_SET))) { +- pos += strlen(PNO_BATCHING_SET) + 1; +- while ((token = strsep(&pos, PNO_PARAMS_DELIMETER)) != NULL) { +- memset(param, 0, sizeof(param)); +- memset(value, 0, sizeof(value)); +- if (token == NULL || !*token) +- break; +- if (*token == '\0') +- continue; +- delim = strchr(token, PNO_PARAM_VALUE_DELLIMETER); +- if (delim != NULL) +- *delim = ' '; +- +- tokens = sscanf(token, "%s %s", param, value); +- if (!strncmp(param, PNO_PARAM_SCANFREQ, strlen(PNO_PARAM_MSCAN))) { +- batch_params.scan_fr = simple_strtol(value, NULL, 0); +- DHD_PNO(("scan_freq : %d\n", batch_params.scan_fr)); +- } else if (!strncmp(param, PNO_PARAM_BESTN, strlen(PNO_PARAM_MSCAN))) { +- batch_params.bestn = simple_strtol(value, NULL, 0); +- DHD_PNO(("bestn : %d\n", batch_params.bestn)); +- } else if (!strncmp(param, PNO_PARAM_MSCAN, strlen(PNO_PARAM_MSCAN))) { +- batch_params.mscan = simple_strtol(value, NULL, 0); +- DHD_PNO(("mscan : %d\n", batch_params.mscan)); +- } else if (!strncmp(param, PNO_PARAM_CHANNEL, strlen(PNO_PARAM_MSCAN))) { +- i = 0; +- pos2 = value; +- tokens = sscanf(value, "<%s>", value); +- if (tokens != 1) { +- err = BCME_ERROR; +- DHD_ERROR(("%s : invalid format for channel" +- " <> params\n", __FUNCTION__)); +- goto exit; +- } +- while ((token2 = strsep(&pos2, +- PNO_PARAM_CHANNEL_DELIMETER)) != NULL) { +- if (token2 == NULL || !*token2) +- break; +- if (*token2 == '\0') +- continue; +- if (*token2 == 'A' || *token2 == 'B') { +- batch_params.band = (*token2 == 'A')? +- WLC_BAND_5G : WLC_BAND_2G; +- DHD_PNO(("band : %s\n", +- (*token2 == 'A')? "A" : "B")); +- } else { +- batch_params.chan_list[i++] = +- simple_strtol(token2, NULL, 0); +- batch_params.nchan++; +- DHD_PNO(("channel :%d\n", +- batch_params.chan_list[i-1])); +- } +- } +- } else if (!strncmp(param, PNO_PARAM_RTT, strlen(PNO_PARAM_MSCAN))) { +- batch_params.rtt = simple_strtol(value, NULL, 0); +- DHD_PNO(("rtt : %d\n", batch_params.rtt)); +- } else { +- DHD_ERROR(("%s : unknown param: %s\n", __FUNCTION__, param)); +- err = BCME_ERROR; +- goto exit; +- } +- } +- err = dhd_dev_pno_set_for_batch(dev, &batch_params); +- if (err < 0) { +- DHD_ERROR(("failed to configure batch scan\n")); +- } else { +- memset(command, 0, total_len); +- err = sprintf(command, "%d", err); +- } +- } else if (!strncmp(pos, PNO_BATCHING_GET, strlen(PNO_BATCHING_GET))) { +- err = dhd_dev_pno_get_for_batch(dev, command, total_len); +- if (err < 0) { +- DHD_ERROR(("failed to getting batching results\n")); +- } +- } else if (!strncmp(pos, PNO_BATCHING_STOP, strlen(PNO_BATCHING_STOP))) { +- err = dhd_dev_pno_stop_for_batch(dev); +- if (err < 0) { +- DHD_ERROR(("failed to stop batching scan\n")); +- } else { +- memset(command, 0, total_len); +- err = sprintf(command, "OK"); +- } +- } else { +- DHD_ERROR(("%s : unknown command\n", __FUNCTION__)); +- err = BCME_ERROR; +- goto exit; +- } +-exit: +- return err; +-} +- +-#ifndef WL_SCHED_SCAN ++#if defined(PNO_SUPPORT) && !defined(WL_SCHED_SCAN) + static int wl_android_set_pno_setup(struct net_device *dev, char *command, int total_len) + { + wlc_ssid_t ssids_local[MAX_PFN_LIST_COUNT]; +@@ -431,16 +334,23 @@ static int wl_android_set_pno_setup(stru + 0x00 + }; + #endif /* PNO_SET_DEBUG */ +- DHD_PNO(("%s: command=%s, len=%d\n", __FUNCTION__, command, total_len)); ++ ++ ANDROID_INFO(("%s: command=%s, len=%d\n", __FUNCTION__, command, total_len)); + + if (total_len < (strlen(CMD_PNOSETUP_SET) + sizeof(cmd_tlv_t))) { +- DHD_ERROR(("%s argument=%d less min size\n", __FUNCTION__, total_len)); ++ ANDROID_ERROR(("%s argument=%d less min size\n", __FUNCTION__, total_len)); + goto exit_proc; + } ++ ++ + #ifdef PNO_SET_DEBUG + memcpy(command, pno_in_example, sizeof(pno_in_example)); ++ for (i = 0; i < sizeof(pno_in_example); i++) ++ printf("%02X ", command[i]); ++ printf("\n"); + total_len = sizeof(pno_in_example); + #endif ++ + str_ptr = command + strlen(CMD_PNOSETUP_SET); + tlv_size_left = total_len - strlen(CMD_PNOSETUP_SET); + +@@ -449,57 +359,56 @@ static int wl_android_set_pno_setup(stru + + if ((cmd_tlv_temp->prefix == PNO_TLV_PREFIX) && + (cmd_tlv_temp->version == PNO_TLV_VERSION) && +- (cmd_tlv_temp->subtype == PNO_TLV_SUBTYPE_LEGACY_PNO)) { ++ (cmd_tlv_temp->subver == PNO_TLV_SUBVERSION)) { + + str_ptr += sizeof(cmd_tlv_t); + tlv_size_left -= sizeof(cmd_tlv_t); + + if ((nssid = wl_iw_parse_ssid_list_tlv(&str_ptr, ssids_local, + MAX_PFN_LIST_COUNT, &tlv_size_left)) <= 0) { +- DHD_ERROR(("SSID is not presented or corrupted ret=%d\n", nssid)); ++ ANDROID_ERROR(("SSID is not presented or corrupted ret=%d\n", nssid)); + goto exit_proc; + } else { + if ((str_ptr[0] != PNO_TLV_TYPE_TIME) || (tlv_size_left <= 1)) { +- DHD_ERROR(("%s scan duration corrupted field size %d\n", ++ ANDROID_ERROR(("%s scan duration corrupted field size %d\n", + __FUNCTION__, tlv_size_left)); + goto exit_proc; + } + str_ptr++; + pno_time = simple_strtoul(str_ptr, &str_ptr, 16); +- DHD_PNO(("%s: pno_time=%d\n", __FUNCTION__, pno_time)); ++ ANDROID_INFO(("%s: pno_time=%d\n", __FUNCTION__, pno_time)); + + if (str_ptr[0] != 0) { + if ((str_ptr[0] != PNO_TLV_FREQ_REPEAT)) { +- DHD_ERROR(("%s pno repeat : corrupted field\n", ++ ANDROID_ERROR(("%s pno repeat : corrupted field\n", + __FUNCTION__)); + goto exit_proc; + } + str_ptr++; + pno_repeat = simple_strtoul(str_ptr, &str_ptr, 16); +- DHD_PNO(("%s :got pno_repeat=%d\n", __FUNCTION__, pno_repeat)); ++ ANDROID_INFO(("%s :got pno_repeat=%d\n", __FUNCTION__, pno_repeat)); + if (str_ptr[0] != PNO_TLV_FREQ_EXPO_MAX) { +- DHD_ERROR(("%s FREQ_EXPO_MAX corrupted field size\n", ++ ANDROID_ERROR(("%s FREQ_EXPO_MAX corrupted field size\n", + __FUNCTION__)); + goto exit_proc; + } + str_ptr++; + pno_freq_expo_max = simple_strtoul(str_ptr, &str_ptr, 16); +- DHD_PNO(("%s: pno_freq_expo_max=%d\n", ++ ANDROID_INFO(("%s: pno_freq_expo_max=%d\n", + __FUNCTION__, pno_freq_expo_max)); + } + } + } else { +- DHD_ERROR(("%s get wrong TLV command\n", __FUNCTION__)); ++ ANDROID_ERROR(("%s get wrong TLV command\n", __FUNCTION__)); + goto exit_proc; + } + +- res = dhd_dev_pno_set_for_ssid(dev, ssids_local, nssid, pno_time, pno_repeat, +- pno_freq_expo_max, NULL, 0); ++ res = dhd_dev_pno_set(dev, ssids_local, nssid, pno_time, pno_repeat, pno_freq_expo_max); ++ + exit_proc: + return res; + } +-#endif /* !WL_SCHED_SCAN */ +-#endif /* PNO_SUPPORT */ ++#endif /* PNO_SUPPORT && !WL_SCHED_SCAN */ + + static int wl_android_get_p2p_dev_addr(struct net_device *ndev, char *command, int total_len) + { +@@ -513,7 +422,6 @@ static int wl_android_get_p2p_dev_addr(s + return bytes_written; + } + +- + /** + * Global function definitions (declared in wl_android.h) + */ +@@ -525,7 +433,7 @@ int wl_android_wifi_on(struct net_device + + printk("%s in\n", __FUNCTION__); + if (!dev) { +- DHD_ERROR(("%s: dev is null\n", __FUNCTION__)); ++ ANDROID_ERROR(("%s: dev is null\n", __FUNCTION__)); + return -EINVAL; + } + +@@ -536,25 +444,40 @@ int wl_android_wifi_on(struct net_device + ret = sdioh_start(NULL, 0); + if (ret == 0) + break; +- DHD_ERROR(("\nfailed to power up wifi chip, retry again (%d left) **\n\n", ++ ANDROID_ERROR(("\nfailed to power up wifi chip, retry again (%d left) **\n\n", + retry+1)); + dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF); + } while (retry-- >= 0); + if (ret != 0) { +- DHD_ERROR(("\nfailed to power up wifi chip, max retry reached **\n\n")); ++ ANDROID_ERROR(("\nfailed to power up wifi chip, max retry reached **\n\n")); + goto exit; + } + ret = dhd_dev_reset(dev, FALSE); ++ if (ret) ++ goto err; + sdioh_start(NULL, 1); + if (!ret) { +- if (dhd_dev_init_ioctl(dev) < 0) ++ if (dhd_dev_init_ioctl(dev) < 0) { + ret = -EFAULT; ++ goto err; ++ } + } ++#if defined(PROP_TXSTATUS) && !defined(PROP_TXSTATUS_VSDB) ++ dhd_wlfc_init(bcmsdh_get_drvdata()); ++#endif + g_wifi_on = TRUE; + } + + exit: + dhd_net_if_unlock(dev); ++ printk("%s: Success\n", __FUNCTION__); ++ return ret; ++err: ++ dhd_dev_reset(dev, TRUE); ++ sdioh_stop(NULL); ++ dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF); ++ dhd_net_if_unlock(dev); ++ printk("%s: Failed\n", __FUNCTION__); + + return ret; + } +@@ -565,12 +488,15 @@ int wl_android_wifi_off(struct net_devic + + printk("%s in\n", __FUNCTION__); + if (!dev) { +- DHD_TRACE(("%s: dev is null\n", __FUNCTION__)); ++ ANDROID_TRACE(("%s: dev is null\n", __FUNCTION__)); + return -EINVAL; + } + + dhd_net_if_lock(dev); + if (g_wifi_on) { ++#if defined(PROP_TXSTATUS) && !defined(PROP_TXSTATUS_VSDB) ++ dhd_wlfc_deinit(bcmsdh_get_drvdata()); ++#endif + ret = dhd_dev_reset(dev, TRUE); + sdioh_stop(NULL); + dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF); +@@ -588,16 +514,15 @@ static int wl_android_set_fwpath(struct + bcm_strncpy_s(fw_path, sizeof(fw_path), + command + strlen(CMD_SETFWPATH) + 1, MOD_PARAM_PATHLEN - 1); + if (strstr(fw_path, "apsta") != NULL) { +- DHD_INFO(("GOT APSTA FIRMWARE\n")); ++ ANDROID_INFO(("GOT APSTA FIRMWARE\n")); + ap_fw_loaded = TRUE; + } else { +- DHD_INFO(("GOT STA FIRMWARE\n")); ++ ANDROID_INFO(("GOT STA FIRMWARE\n")); + ap_fw_loaded = FALSE; + } + return 0; + } + +- + static int + wl_android_set_pmk(struct net_device *dev, char *command, int total_len) + { +@@ -612,14 +537,14 @@ wl_android_set_pmk(struct net_device *de + memcpy((char *)pmk, command + strlen("SET_PMK "), 32); + error = wldev_iovar_setbuf(dev, "okc_info_pmk", pmk, 32, smbuf, sizeof(smbuf), NULL); + if (error) { +- DHD_ERROR(("Failed to set PMK for OKC, error = %d\n", error)); ++ ANDROID_ERROR(("Failed to set PMK for OKC, error = %d\n", error)); + } + #ifdef OKC_DEBUG +- DHD_ERROR(("PMK is ")); ++ ANDROID_ERROR(("PMK is ")); + for (i = 0; i < 32; i++) +- DHD_ERROR(("%02X ", pmk[i])); ++ ANDROID_ERROR(("%02X ", pmk[i])); + +- DHD_ERROR(("\n")); ++ ANDROID_ERROR(("\n")); + #endif + return error; + } +@@ -633,205 +558,38 @@ wl_android_okc_enable(struct net_device + okc_enable = command[strlen(CMD_OKC_ENABLE) + 1] - '0'; + error = wldev_iovar_setint(dev, "okc_enable", okc_enable); + if (error) { +- DHD_ERROR(("Failed to %s OKC, error = %d\n", ++ ANDROID_ERROR(("Failed to %s OKC, error = %d\n", + okc_enable ? "enable" : "disable", error)); + } + +- wldev_iovar_setint(dev, "ccx_enable", 0); +- + return error; + } + +- +- + int wl_android_set_roam_mode(struct net_device *dev, char *command, int total_len) + { + int error = 0; + int mode = 0; + + if (sscanf(command, "%*s %d", &mode) != 1) { +- DHD_ERROR(("%s: Failed to get Parameter\n", __FUNCTION__)); ++ ANDROID_ERROR(("%s: Failed to get Parameter\n", __FUNCTION__)); + return -1; + } + + error = wldev_iovar_setint(dev, "roam_off", mode); + if (error) { +- DHD_ERROR(("%s: Failed to set roaming Mode %d, error = %d\n", ++ ANDROID_ERROR(("%s: Failed to set roaming Mode %d, error = %d\n", + __FUNCTION__, mode, error)); + return -1; + } + else +- DHD_ERROR(("%s: succeeded to set roaming Mode %d, error = %d\n", ++ ANDROID_ERROR(("%s: succeeded to set roaming Mode %d, error = %d\n", + __FUNCTION__, mode, error)); + return 0; + } + +-static int +-wl_android_iolist_add(struct net_device *dev, struct list_head *head, struct io_cfg *config) +-{ +- struct io_cfg *resume_cfg; +- s32 ret; +- +- resume_cfg = kzalloc(sizeof(struct io_cfg), GFP_KERNEL); +- if (!resume_cfg) +- return -ENOMEM; +- +- if (config->iovar) { +- ret = wldev_iovar_getint(dev, config->iovar, &resume_cfg->param); +- if (ret) { +- DHD_ERROR(("%s: Failed to get current %s value\n", +- __FUNCTION__, config->iovar)); +- goto error; +- } +- +- ret = wldev_iovar_setint(dev, config->iovar, config->param); +- if (ret) { +- DHD_ERROR(("%s: Failed to set %s to %d\n", __FUNCTION__, +- config->iovar, config->param)); +- goto error; +- } +- +- resume_cfg->iovar = config->iovar; +- } else { +- resume_cfg->arg = kzalloc(config->len, GFP_KERNEL); +- if (!resume_cfg->arg) { +- ret = -ENOMEM; +- goto error; +- } +- ret = wldev_ioctl(dev, config->ioctl, resume_cfg->arg, config->len, false); +- if (ret) { +- DHD_ERROR(("%s: Failed to get ioctl %d\n", __FUNCTION__, +- config->ioctl)); +- goto error; +- } +- ret = wldev_ioctl(dev, config->ioctl + 1, config->arg, config->len, true); +- if (ret) { +- DHD_ERROR(("%s: Failed to set %s to %d\n", __FUNCTION__, +- config->iovar, config->param)); +- goto error; +- } +- if (config->ioctl + 1 == WLC_SET_PM) +- wl_cfg80211_update_power_mode(dev); +- resume_cfg->ioctl = config->ioctl; +- resume_cfg->len = config->len; +- } +- +- list_add(&resume_cfg->list, head); +- +- return 0; +-error: +- kfree(resume_cfg->arg); +- kfree(resume_cfg); +- return ret; +-} +- +-static void +-wl_android_iolist_resume(struct net_device *dev, struct list_head *head) +-{ +- struct io_cfg *config; +- struct list_head *cur, *q; +- s32 ret = 0; +- +- list_for_each_safe(cur, q, head) { +- config = list_entry(cur, struct io_cfg, list); +- if (config->iovar) { +- if (!ret) +- ret = wldev_iovar_setint(dev, config->iovar, +- config->param); +- } else { +- if (!ret) +- ret = wldev_ioctl(dev, config->ioctl + 1, +- config->arg, config->len, true); +- if (config->ioctl + 1 == WLC_SET_PM) +- wl_cfg80211_update_power_mode(dev); +- kfree(config->arg); +- } +- list_del(cur); +- kfree(config); +- } +-} +- +-static int +-wl_android_set_miracast(struct net_device *dev, char *command, int total_len) +-{ +- int mode, val; +- int ret = 0; +- struct io_cfg config; +- +- if (sscanf(command, "%*s %d", &mode) != 1) { +- DHD_ERROR(("%s: Failed to get Parameter\n", __FUNCTION__)); +- return -1; +- } +- +- DHD_INFO(("%s: enter miracast mode %d\n", __FUNCTION__, mode)); +- +- if (miracast_cur_mode == mode) +- return 0; +- +- wl_android_iolist_resume(dev, &miracast_resume_list); +- miracast_cur_mode = MIRACAST_MODE_OFF; +- +- switch (mode) { +- case MIRACAST_MODE_SOURCE: +- /* setting mchan_algo to platform specific value */ +- config.iovar = "mchan_algo"; +- config.param = MIRACAST_MCHAN_ALGO; +- ret = wl_android_iolist_add(dev, &miracast_resume_list, &config); +- if (ret) +- goto resume; +- +- /* setting mchan_bw to platform specific value */ +- config.iovar = "mchan_bw"; +- config.param = MIRACAST_MCHAN_BW; +- ret = wl_android_iolist_add(dev, &miracast_resume_list, &config); +- if (ret) +- goto resume; +- +- /* setting apmdu to platform specific value */ +- config.iovar = "ampdu_mpdu"; +- config.param = MIRACAST_AMPDU_SIZE; +- ret = wl_android_iolist_add(dev, &miracast_resume_list, &config); +- if (ret) +- goto resume; +- /* FALLTROUGH */ +- /* Source mode shares most configurations with sink mode. +- * Fall through here to avoid code duplication +- */ +- case MIRACAST_MODE_SINK: +- /* disable internal roaming */ +- config.iovar = "roam_off"; +- config.param = 1; +- ret = wl_android_iolist_add(dev, &miracast_resume_list, &config); +- if (ret) +- goto resume; +- /* tunr off pm */ +- val = 0; +- config.iovar = NULL; +- config.ioctl = WLC_GET_PM; +- config.arg = &val; +- config.len = sizeof(int); +- ret = wl_android_iolist_add(dev, &miracast_resume_list, &config); +- if (ret) +- goto resume; +- +- break; +- case MIRACAST_MODE_OFF: +- default: +- break; +- } +- miracast_cur_mode = mode; +- +- return 0; +- +-resume: +- DHD_ERROR(("%s: turnoff miracast mode because of err %d\n", __FUNCTION__, ret)); +- wl_android_iolist_resume(dev, &miracast_resume_list); +- return ret; +-} +- + int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) + { +-#define PRIVATE_COMMAND_MAX_LEN 8192 ++#define PRIVATE_COMMAND_MAX_LEN 8192 + int ret = 0; + char *command = NULL; + int bytes_written = 0; +@@ -849,14 +607,13 @@ int wl_android_priv_cmd(struct net_devic + } + if (priv_cmd.total_len > PRIVATE_COMMAND_MAX_LEN) + { +- DHD_ERROR(("%s: too long priavte command\n", __FUNCTION__)); ++ ANDROID_ERROR(("%s: too long priavte command\n", __FUNCTION__)); + ret = -EINVAL; +- goto exit; + } +- command = kmalloc((priv_cmd.total_len + 1), GFP_KERNEL); ++ command = kmalloc(priv_cmd.total_len, GFP_KERNEL); + if (!command) + { +- DHD_ERROR(("%s: failed to allocate memory\n", __FUNCTION__)); ++ ANDROID_ERROR(("%s: failed to allocate memory\n", __FUNCTION__)); + ret = -ENOMEM; + goto exit; + } +@@ -864,12 +621,11 @@ int wl_android_priv_cmd(struct net_devic + ret = -EFAULT; + goto exit; + } +- command[priv_cmd.total_len] = '\0'; + +- DHD_INFO(("%s: Android private cmd \"%s\" on %s\n", __FUNCTION__, command, ifr->ifr_name)); ++ ANDROID_INFO(("%s: Android private cmd \"%s\" on %s\n", __FUNCTION__, command, ifr->ifr_name)); + + if (strnicmp(command, CMD_START, strlen(CMD_START)) == 0) { +- DHD_INFO(("%s, Received regular START command\n", __FUNCTION__)); ++ ANDROID_INFO(("%s, Received regular START command\n", __FUNCTION__)); + bytes_written = wl_android_wifi_on(net); + } + else if (strnicmp(command, CMD_SETFWPATH, strlen(CMD_SETFWPATH)) == 0) { +@@ -877,7 +633,7 @@ int wl_android_priv_cmd(struct net_devic + } + + if (!g_wifi_on) { +- DHD_ERROR(("%s: Ignore private cmd \"%s\" - iface %s is down\n", ++ ANDROID_ERROR(("%s: Ignore private cmd \"%s\" - iface %s is down\n", + __FUNCTION__, command, ifr->ifr_name)); + ret = 0; + goto exit; +@@ -942,7 +698,16 @@ int wl_android_priv_cmd(struct net_devic + } + else if (strnicmp(command, CMD_SETBAND, strlen(CMD_SETBAND)) == 0) { + uint band = *(command + strlen(CMD_SETBAND) + 1) - '0'; ++#ifdef WL_HOST_BAND_MGMT ++ if (wl_cfg80211_set_band(net, band) < 0) { ++ bytes_written = -1; ++ goto exit; ++ } ++ if (band == WLC_BAND_AUTO) ++ bytes_written = wldev_set_band(net, band); ++#else + bytes_written = wldev_set_band(net, band); ++#endif /* WL_HOST_BAND_MGMT */ + } + else if (strnicmp(command, CMD_GETBAND, strlen(CMD_GETBAND)) == 0) { + bytes_written = wl_android_get_band(net, command, priv_cmd.total_len); +@@ -951,28 +716,21 @@ int wl_android_priv_cmd(struct net_devic + /* CUSTOMER_SET_COUNTRY feature is define for only GGSM model */ + else if (strnicmp(command, CMD_COUNTRY, strlen(CMD_COUNTRY)) == 0) { + char *country_code = command + strlen(CMD_COUNTRY) + 1; +- bytes_written = wldev_set_country(net, country_code, true, true); ++ bytes_written = wldev_set_country(net, country_code); + } + #endif /* WL_CFG80211 */ +- +- +-#ifdef PNO_SUPPORT +-#ifndef WL_SCHED_SCAN ++#if defined(PNO_SUPPORT) && !defined(WL_SCHED_SCAN) + else if (strnicmp(command, CMD_PNOSSIDCLR_SET, strlen(CMD_PNOSSIDCLR_SET)) == 0) { +- bytes_written = dhd_dev_pno_stop_for_ssid(net); ++ bytes_written = dhd_dev_pno_reset(net); + } + else if (strnicmp(command, CMD_PNOSETUP_SET, strlen(CMD_PNOSETUP_SET)) == 0) { + bytes_written = wl_android_set_pno_setup(net, command, priv_cmd.total_len); + } + else if (strnicmp(command, CMD_PNOENABLE_SET, strlen(CMD_PNOENABLE_SET)) == 0) { +- int enable = *(command + strlen(CMD_PNOENABLE_SET) + 1) - '0'; +- bytes_written = (enable)? 0 : dhd_dev_pno_stop_for_ssid(net); +- } +-#endif +- else if (strnicmp(command, CMD_WLS_BATCHING, strlen(CMD_WLS_BATCHING)) == 0) { +- bytes_written = wls_parse_batching_cmd(net, command, priv_cmd.total_len); ++ uint pfn_enabled = *(command + strlen(CMD_PNOENABLE_SET) + 1) - '0'; ++ bytes_written = dhd_dev_pno_enable(net, pfn_enabled); + } +-#endif /* PNO_SUPPORT */ ++#endif /* PNO_SUPPORT && !WL_SCHED_SCAN */ + else if (strnicmp(command, CMD_P2P_DEV_ADDR, strlen(CMD_P2P_DEV_ADDR)) == 0) { + bytes_written = wl_android_get_p2p_dev_addr(net, command, priv_cmd.total_len); + } +@@ -1005,10 +763,8 @@ int wl_android_priv_cmd(struct net_devic + bytes_written = wl_android_okc_enable(net, command, priv_cmd.total_len); + else if (strnicmp(command, CMD_SETROAMMODE, strlen(CMD_SETROAMMODE)) == 0) + bytes_written = wl_android_set_roam_mode(net, command, priv_cmd.total_len); +- else if (strnicmp(command, CMD_MIRACAST, strlen(CMD_MIRACAST)) == 0) +- bytes_written = wl_android_set_miracast(net, command, priv_cmd.total_len); + else { +- DHD_ERROR(("Unknown PRIVATE command %s - ignored\n", command)); ++ ANDROID_ERROR(("Unknown PRIVATE command %s - ignored\n", command)); + snprintf(command, 3, "OK"); + bytes_written = strlen("OK"); + } +@@ -1017,14 +773,14 @@ int wl_android_priv_cmd(struct net_devic + if ((bytes_written == 0) && (priv_cmd.total_len > 0)) + command[0] = '\0'; + if (bytes_written >= priv_cmd.total_len) { +- DHD_ERROR(("%s: bytes_written = %d\n", __FUNCTION__, bytes_written)); ++ ANDROID_ERROR(("%s: bytes_written = %d\n", __FUNCTION__, bytes_written)); + bytes_written = priv_cmd.total_len; + } else { + bytes_written++; + } + priv_cmd.used_len = bytes_written; + if (copy_to_user(priv_cmd.buf, command, bytes_written)) { +- DHD_ERROR(("%s: failed to copy data to user buffer\n", __FUNCTION__)); ++ ANDROID_ERROR(("%s: failed to copy data to user buffer\n", __FUNCTION__)); + ret = -EFAULT; + } + } +@@ -1045,17 +801,14 @@ int wl_android_init(void) + { + int ret = 0; + ++ dhd_msg_level |= DHD_ERROR_VAL; + #ifdef ENABLE_INSMOD_NO_FW_LOAD + dhd_download_fw_on_driverload = FALSE; + #endif /* ENABLE_INSMOD_NO_FW_LOAD */ +-#if defined(CUSTOMER_HW2) + if (!iface_name[0]) { + memset(iface_name, 0, IFNAMSIZ); + bcm_strncpy_s(iface_name, IFNAMSIZ, "wlan", IFNAMSIZ); + } +-#endif +- +- + return ret; + } + +@@ -1063,37 +816,459 @@ int wl_android_exit(void) + { + int ret = 0; + +- + return ret; + } + + void wl_android_post_init(void) + { +- +-#ifdef ENABLE_4335BT_WAR +- bcm_bt_unlock(lock_cookie_wifi); +- printk("%s: btlock released\n", __FUNCTION__); +-#endif /* ENABLE_4335BT_WAR */ +- + if (!dhd_download_fw_on_driverload) { + /* Call customer gpio to turn off power with WL_REG_ON signal */ + dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF); +- g_wifi_on = FALSE; ++ g_wifi_on = 0; ++ } ++} ++ ++#if defined(RSSIAVG) ++void ++wl_free_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl) ++{ ++ wl_rssi_cache_t *node, *cur, **rssi_head; ++ int i=0; ++ ++ rssi_head = &rssi_cache_ctrl->m_cache_head; ++ node = *rssi_head; ++ ++ for (;node;) { ++ ANDROID_INFO(("%s: Free %d with BSSID %pM\n", ++ __FUNCTION__, i, &node->BSSID)); ++ cur = node; ++ node = cur->next; ++ kfree(cur); ++ i++; ++ } ++ *rssi_head = NULL; ++} ++ ++void ++wl_delete_dirty_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl) ++{ ++ wl_rssi_cache_t *node, *prev, **rssi_head; ++ int i = -1, tmp = 0; ++#if defined(BSSCACHE) ++ int max = BSSCACHE_LEN; ++#else ++ int max = RSSICACHE_LEN; ++#endif ++ ++ rssi_head = &rssi_cache_ctrl->m_cache_head; ++ node = *rssi_head; ++ prev = node; ++ for (;node;) { ++ i++; ++ if (node->dirty >= max || node->dirty >= RSSICACHE_LEN) { ++ if (node == *rssi_head) { ++ tmp = 1; ++ *rssi_head = node->next; ++ } else { ++ tmp = 0; ++ prev->next = node->next; ++ } ++ ANDROID_INFO(("%s: Del %d with BSSID %pM\n", ++ __FUNCTION__, i, &node->BSSID)); ++ kfree(node); ++ if (tmp == 1) { ++ node = *rssi_head; ++ prev = node; ++ } else { ++ node = prev->next; ++ } ++ continue; ++ } ++ prev = node; ++ node = node->next; ++ } ++} ++ ++void ++wl_reset_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl) ++{ ++ wl_rssi_cache_t *node, **rssi_head; ++ ++ rssi_head = &rssi_cache_ctrl->m_cache_head; ++ ++ /* reset dirty */ ++ node = *rssi_head; ++ for (;node;) { ++ node->dirty += 1; ++ node = node->next; ++ } ++} ++ ++void ++wl_update_connected_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, struct net_device *net) ++{ ++ wl_rssi_cache_t *node, *prev, **rssi_head; ++ int j, k=0; ++ int rssi, error; ++ struct ether_addr bssid; ++ ++ error = wldev_ioctl(net, WLC_GET_BSSID, &bssid, sizeof(bssid), false); ++ if (error) ++ return; ++ error = wldev_get_rssi(net, &rssi); ++ if (error) ++ return; ++ ++ /* update RSSI */ ++ rssi_head = &rssi_cache_ctrl->m_cache_head; ++ node = *rssi_head; ++ for (;node;) { ++ if (!memcmp(&node->BSSID, &bssid, ETHER_ADDR_LEN)) { ++ ANDROID_INFO(("%s: Update %d with BSSID %pM, RSSI=%d\n", ++ __FUNCTION__, k, &bssid, rssi)); ++ for(j=0; jRSSI[j] = node->RSSI[j+1]; ++ node->RSSI[j] = rssi; ++ node->dirty = 0; ++ break; ++ } ++ prev = node; ++ node = node->next; ++ k++; ++ } ++} ++ ++void ++wl_update_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, wl_scan_results_t *ss_list) ++{ ++ wl_rssi_cache_t *node, *prev, *leaf, **rssi_head; ++ wl_bss_info_t *bi = NULL; ++ int i, j, k; ++ ++ if (!ss_list->count) ++ return; ++ ++ rssi_head = &rssi_cache_ctrl->m_cache_head; ++ ++ /* update RSSI */ ++ for (i = 0; i < ss_list->count; i++) { ++ node = *rssi_head; ++ prev = NULL; ++ k = 0; ++ bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : ss_list->bss_info; ++ for (;node;) { ++ if (!memcmp(&node->BSSID, &bi->BSSID, ETHER_ADDR_LEN)) { ++ ANDROID_INFO(("%s: Update %d with BSSID %pM, RSSI=%d, SSID \"%s\"\n", ++ __FUNCTION__, k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID)); ++ for(j=0; jRSSI[j] = node->RSSI[j+1]; ++ node->RSSI[j] = dtoh16(bi->RSSI); ++ node->dirty = 0; ++ break; ++ } ++ prev = node; ++ node = node->next; ++ k++; ++ } ++ ++ if (node) ++ continue; ++ ++ leaf = kmalloc(sizeof(wl_rssi_cache_t), GFP_KERNEL); ++ if (!leaf) { ++ ANDROID_ERROR(("%s: Memory alloc failure %d\n", ++ __FUNCTION__, sizeof(wl_rssi_cache_t))); ++ return; ++ } ++ ANDROID_INFO(("%s: Add %d with cached BSSID %pM, RSSI=%d, SSID \"%s\" in the leaf\n", ++ __FUNCTION__, k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID)); ++ ++ leaf->next = NULL; ++ leaf->dirty = 0; ++ memcpy(&leaf->BSSID, &bi->BSSID, ETHER_ADDR_LEN); ++ for (j=0; jRSSI[j] = dtoh16(bi->RSSI); ++ ++ if (!prev) ++ *rssi_head = leaf; ++ else ++ prev->next = leaf; ++ } ++} ++ ++int16 ++wl_get_avg_rssi(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, void *addr) ++{ ++ wl_rssi_cache_t *node, **rssi_head; ++ int j, rssi_sum, rssi=-200; ++ ++ rssi_head = &rssi_cache_ctrl->m_cache_head; ++ ++ /* reset dirty */ ++ node = *rssi_head; ++ for (;node;) { ++ if (!memcmp(&node->BSSID, addr, ETHER_ADDR_LEN)) { ++ rssi_sum = 0; ++ rssi = 0; ++ for (j=0; jRSSI[RSSIAVG_LEN-j-1]; ++ rssi = rssi_sum / j; ++ break; ++ } ++ node = node->next; ++ } ++ if (rssi >= -2) ++ rssi = -2; ++ if (rssi == -200) { ++ ANDROID_ERROR(("%s: BSSID %pM does not in RSSI cache\n", ++ __FUNCTION__, addr)); ++ } ++ return (int16)rssi; ++} ++#endif ++ ++#if defined(RSSIOFFSET) ++int ++wl_update_rssi_offset(int rssi) ++{ ++ uint chip, chiprev; ++ ++ chip = dhd_bus_chip_id(bcmsdh_get_drvdata()); ++ chiprev = dhd_bus_chiprev_id(bcmsdh_get_drvdata()); ++ if (chip == BCM4330_CHIP_ID && chiprev == BCM4330B2_CHIP_REV) { ++#if defined(RSSIOFFSET_NEW) ++ int j; ++ for (j=0; j= -2) ++ rssi = -2; ++ return rssi; ++} ++#endif ++ ++#if defined(BSSCACHE) ++#define WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN 32 ++ ++void ++wl_free_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl) ++{ ++ wl_bss_cache_t *node, *cur, **bss_head; ++ int i=0; ++ ++ ANDROID_TRACE(("%s called\n", __FUNCTION__)); ++ ++ bss_head = &bss_cache_ctrl->m_cache_head; ++ node = *bss_head; ++ ++ for (;node;) { ++ ANDROID_TRACE(("%s: Free %d with BSSID %pM\n", ++ __FUNCTION__, i, &node->results.bss_info->BSSID)); ++ cur = node; ++ node = cur->next; ++ kfree(cur); ++ i++; ++ } ++ *bss_head = NULL; ++} ++ ++void ++wl_delete_dirty_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl) ++{ ++ wl_bss_cache_t *node, *prev, **bss_head; ++ int i = -1, tmp = 0; ++ ++ bss_head = &bss_cache_ctrl->m_cache_head; ++ node = *bss_head; ++ prev = node; ++ for (;node;) { ++ i++; ++ if (node->dirty >= BSSCACHE_LEN) { ++ if (node == *bss_head) { ++ tmp = 1; ++ *bss_head = node->next; ++ } else { ++ tmp = 0; ++ prev->next = node->next; ++ } ++ ANDROID_TRACE(("%s: Del %d with BSSID %pM, RSSI=%d, SSID \"%s\"\n", ++ __FUNCTION__, i, &node->results.bss_info->BSSID, ++ dtoh16(node->results.bss_info->RSSI), node->results.bss_info->SSID)); ++ kfree(node); ++ if (tmp == 1) { ++ node = *bss_head; ++ prev = node; ++ } else { ++ node = prev->next; ++ } ++ continue; ++ } ++ prev = node; ++ node = node->next; ++ } ++} ++ ++void ++wl_reset_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl) ++{ ++ wl_bss_cache_t *node, **bss_head; ++ ++ bss_head = &bss_cache_ctrl->m_cache_head; ++ ++ /* reset dirty */ ++ node = *bss_head; ++ for (;node;) { ++ node->dirty += 1; ++ node = node->next; ++ } ++} ++ ++void ++wl_update_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl, wl_scan_results_t *ss_list) ++{ ++ wl_bss_cache_t *node, *prev, *leaf, *tmp, **bss_head; ++ wl_bss_info_t *bi = NULL; ++ int i, k=0; ++ ++ if (!ss_list->count) ++ return; ++ ++ bss_head = &bss_cache_ctrl->m_cache_head; ++ ++ for (i=0; i < ss_list->count; i++) { ++ node = *bss_head; ++ prev = NULL; ++ bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : ss_list->bss_info; ++ ++ for (;node;) { ++ if (!memcmp(&node->results.bss_info->BSSID, &bi->BSSID, ETHER_ADDR_LEN)) { ++ tmp = node; ++ leaf = kmalloc(dtoh32(bi->length) + WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN, GFP_KERNEL); ++ if (!leaf) { ++ ANDROID_ERROR(("%s: Memory alloc failure %d and keep old BSS info\n", ++ __FUNCTION__, dtoh32(bi->length) + WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN)); ++ break; ++ } ++ ++ memcpy(leaf->results.bss_info, bi, dtoh32(bi->length)); ++ leaf->next = node->next; ++ leaf->dirty = 0; ++ leaf->results.count = 1; ++ leaf->results.version = ss_list->version; ++ ANDROID_TRACE(("%s: Update %d with BSSID %pM, RSSI=%d, SSID \"%s\"\n", ++ __FUNCTION__, k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID)); ++ if (!prev) ++ *bss_head = leaf; ++ else ++ prev->next = leaf; ++ node = leaf; ++ prev = node; ++ ++ kfree(tmp); ++ k++; ++ break; ++ } ++ prev = node; ++ node = node->next; ++ } ++ ++ if (node) ++ continue; ++ ++ leaf = kmalloc(dtoh32(bi->length) + WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN, GFP_KERNEL); ++ if (!leaf) { ++ ANDROID_ERROR(("%s: Memory alloc failure %d\n", __FUNCTION__, ++ dtoh32(bi->length) + WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN)); ++ return; ++ } ++ ANDROID_TRACE(("%s: Add %d with cached BSSID %pM, RSSI=%d, SSID \"%s\" in the leaf\n", ++ __FUNCTION__, k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID)); ++ ++ memcpy(leaf->results.bss_info, bi, dtoh32(bi->length)); ++ leaf->next = NULL; ++ leaf->dirty = 0; ++ leaf->results.count = 1; ++ leaf->results.version = ss_list->version; ++ k++; ++ ++ if (!prev) ++ *bss_head = leaf; ++ else ++ prev->next = leaf; ++ } ++} ++ ++void ++wl_run_bss_cache_timer(wl_bss_cache_ctrl_t *bss_cache_ctrl, int kick_off) ++{ ++ struct timer_list **timer; ++ ++ timer = &bss_cache_ctrl->m_timer; ++ ++ if (*timer) { ++ if (kick_off) { ++ (*timer)->expires = jiffies + BSSCACHE_TIME * HZ / 1000; ++ add_timer(*timer); ++ ANDROID_TRACE(("%s: timer starts\n", __FUNCTION__)); ++ } else { ++ del_timer_sync(*timer); ++ ANDROID_TRACE(("%s: timer stops\n", __FUNCTION__)); ++ } + } + } + ++void ++wl_set_bss_cache_timer_flag(ulong data) ++{ ++ wl_bss_cache_ctrl_t *bss_cache_ctrl = (wl_bss_cache_ctrl_t *)data; ++ ++ bss_cache_ctrl->m_timer_expired = 1; ++ ANDROID_TRACE(("%s called\n", __FUNCTION__)); ++} ++ ++void ++wl_release_bss_cache_ctrl(wl_bss_cache_ctrl_t *bss_cache_ctrl) ++{ ++ ANDROID_TRACE(("%s:\n", __FUNCTION__)); ++ wl_free_bss_cache(bss_cache_ctrl); ++ wl_run_bss_cache_timer(bss_cache_ctrl, 0); ++ if (bss_cache_ctrl->m_timer) { ++ kfree(bss_cache_ctrl->m_timer); ++ } ++} ++ ++void ++wl_init_bss_cache_ctrl(wl_bss_cache_ctrl_t *bss_cache_ctrl) ++{ ++ ANDROID_TRACE(("%s:\n", __FUNCTION__)); ++ bss_cache_ctrl->m_timer_expired = 0; ++ ++ bss_cache_ctrl->m_timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL); ++ if (!bss_cache_ctrl->m_timer) { ++ ANDROID_ERROR(("%s: Memory alloc failure\n", __FUNCTION__ )); ++ return; ++ } ++ init_timer(bss_cache_ctrl->m_timer); ++ bss_cache_ctrl->m_timer->function = (void *)wl_set_bss_cache_timer_flag; ++ bss_cache_ctrl->m_timer->data = (ulong)bss_cache_ctrl; ++} ++#endif + + /** + * Functions for Android WiFi card detection + */ + #if defined(CONFIG_WIFI_CONTROL_FUNC) + +-bool g_wifi_poweron = FALSE; + static int g_wifidev_registered = 0; + static struct semaphore wifi_control_sem; + static struct wifi_platform_data *wifi_control_data = NULL; + static struct resource *wifi_irqres = NULL; +-static struct regulator *wifi_regulator = NULL; + + static int wifi_add_dev(void); + static void wifi_del_dev(void); +@@ -1105,7 +1280,7 @@ int wl_android_wifictrl_func_add(void) + + ret = wifi_add_dev(); + if (ret) { +- DHD_ERROR(("%s: platform_driver_register failed\n", __FUNCTION__)); ++ ANDROID_ERROR(("%s: platform_driver_register failed\n", __FUNCTION__)); + return ret; + } + g_wifidev_registered = 1; +@@ -1113,7 +1288,7 @@ int wl_android_wifictrl_func_add(void) + /* Waiting callback after platform_driver_register is done or exit with error */ + if (down_timeout(&wifi_control_sem, msecs_to_jiffies(1000)) != 0) { + ret = -EINVAL; +- DHD_ERROR(("%s: platform_driver_register timeout\n", __FUNCTION__)); ++ ANDROID_ERROR(("%s: platform_driver_register timeout\n", __FUNCTION__)); + } + + return ret; +@@ -1134,14 +1309,14 @@ void* wl_android_prealloc(int section, u + if (wifi_control_data && wifi_control_data->mem_prealloc) { + alloc_ptr = wifi_control_data->mem_prealloc(section, size); + if (alloc_ptr) { +- DHD_INFO(("success alloc section %d\n", section)); ++ ANDROID_INFO(("success alloc section %d\n", section)); + if (size != 0L) + bzero(alloc_ptr, size); + return alloc_ptr; + } + } + +- DHD_ERROR(("can't alloc section %d\n", section)); ++ ANDROID_ERROR(("can't alloc section %d\n", section)); + return NULL; + } + +@@ -1160,38 +1335,19 @@ int wifi_get_irq_number(unsigned long *i + + int wifi_set_power(int on, unsigned long msec) + { +- int ret = 0; +- DHD_ERROR(("%s = %d\n", __FUNCTION__, on)); +- if (wifi_regulator && on) +- ret = regulator_enable(wifi_regulator); ++ ANDROID_ERROR(("%s = %d\n", __FUNCTION__, on)); + if (wifi_control_data && wifi_control_data->set_power) { +-#ifdef ENABLE_4335BT_WAR +- if (on) { +- printk("WiFi: trying to acquire BT lock\n"); +- if (bcm_bt_lock(lock_cookie_wifi) != 0) +- printk("** WiFi: timeout in acquiring bt lock**\n"); +- printk("%s: btlock acquired\n", __FUNCTION__); +- } +- else { +- /* For a exceptional case, release btlock */ +- bcm_bt_unlock(lock_cookie_wifi); +- } +-#endif /* ENABLE_4335BT_WAR */ +- ret = wifi_control_data->set_power(on); ++ wifi_control_data->set_power(on); + } +- +- if (wifi_regulator && !on) +- ret = regulator_disable(wifi_regulator); +- +- if (msec && !ret) +- OSL_SLEEP(msec); +- return ret; ++ if (msec) ++ msleep(msec); ++ return 0; + } + + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)) + int wifi_get_mac_addr(unsigned char *buf) + { +- DHD_ERROR(("%s\n", __FUNCTION__)); ++ ANDROID_ERROR(("%s\n", __FUNCTION__)); + if (!buf) + return -EINVAL; + if (wifi_control_data && wifi_control_data->get_mac_addr) { +@@ -1204,7 +1360,7 @@ int wifi_get_mac_addr(unsigned char *buf + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) + void *wifi_get_country_code(char *ccode) + { +- DHD_TRACE(("%s\n", __FUNCTION__)); ++ ANDROID_TRACE(("%s\n", __FUNCTION__)); + if (!ccode) + return NULL; + if (wifi_control_data && wifi_control_data->get_country_code) { +@@ -1216,63 +1372,25 @@ void *wifi_get_country_code(char *ccode) + + static int wifi_set_carddetect(int on) + { +- DHD_ERROR(("%s = %d\n", __FUNCTION__, on)); ++ ANDROID_ERROR(("%s = %d\n", __FUNCTION__, on)); + if (wifi_control_data && wifi_control_data->set_carddetect) { + wifi_control_data->set_carddetect(on); + } + return 0; + } + +-static struct resource *get_wifi_irqres_from_of(struct platform_device *pdev) +-{ +- static struct resource gpio_wifi_irqres; +- int irq; +- int gpio = of_get_gpio(pdev->dev.of_node, 0); +- if (gpio < 0) +- return NULL; +- irq = gpio_to_irq(gpio); +- if (irq < 0) +- return NULL; +- +- gpio_wifi_irqres.name = "bcmdhd_wlan_irq"; +- gpio_wifi_irqres.start = irq; +- gpio_wifi_irqres.end = irq; +- gpio_wifi_irqres.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | +- IORESOURCE_IRQ_SHAREABLE; +- +- return &gpio_wifi_irqres; +-} +- + static int wifi_probe(struct platform_device *pdev) + { +- int err; +- struct regulator *regulator; + struct wifi_platform_data *wifi_ctrl = + (struct wifi_platform_data *)(pdev->dev.platform_data); + +- if (!wifi_ctrl) { +- regulator = regulator_get(&pdev->dev, "wlreg_on"); +- if (IS_ERR(regulator)) +- return PTR_ERR(regulator); +- wifi_regulator = regulator; +- } +- + wifi_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "bcmdhd_wlan_irq"); + if (wifi_irqres == NULL) + wifi_irqres = platform_get_resource_byname(pdev, + IORESOURCE_IRQ, "bcm4329_wlan_irq"); +- if (wifi_irqres == NULL) +- wifi_irqres = get_wifi_irqres_from_of(pdev); + wifi_control_data = wifi_ctrl; +- err = wifi_set_power(1, 0); /* Power On */ +- if (unlikely(err)) { +- DHD_ERROR(("%s: set_power failed. err=%d\n", __FUNCTION__, err)); +- wifi_set_power(0, WIFI_TURNOFF_DELAY); +- /* WL_REG_ON state unknown, Power off forcely */ +- } else { +- wifi_set_carddetect(1); /* CardDetect (0->1) */ +- g_wifi_poweron = TRUE; +- } ++ wifi_set_power(1, 0); /* Power On */ ++ wifi_set_carddetect(1); /* CardDetect (0->1) */ + + up(&wifi_control_sem); + return 0; +@@ -1282,24 +1400,12 @@ static int wifi_remove(struct platform_d + { + struct wifi_platform_data *wifi_ctrl = + (struct wifi_platform_data *)(pdev->dev.platform_data); +- struct io_cfg *cur, *q; + +- DHD_ERROR(("## %s\n", __FUNCTION__)); ++ ANDROID_ERROR(("## %s\n", __FUNCTION__)); + wifi_control_data = wifi_ctrl; + +- if (g_wifi_poweron) { + wifi_set_power(0, WIFI_TURNOFF_DELAY); /* Power Off */ + wifi_set_carddetect(0); /* CardDetect (1->0) */ +- g_wifi_poweron = FALSE; +- list_for_each_entry_safe(cur, q, &miracast_resume_list, list) { +- list_del(&cur->list); +- kfree(cur); +- } +- } +- if (wifi_regulator) { +- regulator_put(wifi_regulator); +- wifi_regulator = NULL; +- } + + up(&wifi_control_sem); + return 0; +@@ -1307,7 +1413,11 @@ static int wifi_remove(struct platform_d + + static int wifi_suspend(struct platform_device *pdev, pm_message_t state) + { +- DHD_TRACE(("##> %s\n", __FUNCTION__)); ++ ANDROID_TRACE(("##> %s\n", __FUNCTION__)); ++#if defined(CONFIG_ARCH_RHEA) || defined(CONFIG_ARCH_CAPRI) ++ if (dhd_os_check_wakelock(bcmsdh_get_drvdata())) ++ return -EBUSY; ++#endif /* defined(CONFIG_ARCH_RHEA) || defined(CONFIG_ARCH_CAPRI) */ + #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY) && 1 + bcmsdh_oob_intr_set(0); + #endif /* (OOB_INTR_ONLY) */ +@@ -1316,7 +1426,7 @@ static int wifi_suspend(struct platform_ + + static int wifi_resume(struct platform_device *pdev) + { +- DHD_TRACE(("##> %s\n", __FUNCTION__)); ++ ANDROID_TRACE(("##> %s\n", __FUNCTION__)); + #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY) && 1 + if (dhd_os_check_if_up(bcmsdh_get_drvdata())) + bcmsdh_oob_intr_set(1); +@@ -1324,12 +1434,6 @@ static int wifi_resume(struct platform_d + return 0; + } + +-static const struct of_device_id wifi_device_dt_match[] = { +- { .compatible = "android,bcmdhd_wlan", }, +- {}, +-}; +-MODULE_DEVICE_TABLE(of, wifi_device_dt_match); +- + static struct platform_driver wifi_device = { + .probe = wifi_probe, + .remove = wifi_remove, +@@ -1337,7 +1441,6 @@ static struct platform_driver wifi_devic + .resume = wifi_resume, + .driver = { + .name = "bcmdhd_wlan", +- .of_match_table = wifi_device_dt_match, + } + }; + +@@ -1354,7 +1457,7 @@ static struct platform_driver wifi_devic + static int wifi_add_dev(void) + { + int ret = 0; +- DHD_TRACE(("## Calling platform_driver_register\n")); ++ ANDROID_TRACE(("## Calling platform_driver_register\n")); + ret = platform_driver_register(&wifi_device); + if (ret) + return ret; +@@ -1365,7 +1468,7 @@ static int wifi_add_dev(void) + + static void wifi_del_dev(void) + { +- DHD_TRACE(("## Unregister platform_driver_register\n")); ++ ANDROID_TRACE(("## Unregister platform_driver_register\n")); + platform_driver_unregister(&wifi_device); + platform_driver_unregister(&wifi_device_legacy); + } +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/wl_android.h linux-sunxi-new/drivers/net/wireless/bcmdhd/wl_android.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/wl_android.h 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/wl_android.h 2014-02-15 00:43:44.795014136 +0100 +@@ -1,7 +1,7 @@ + /* + * Linux cfg80211 driver - Android related functions + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -21,7 +21,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: wl_android.h 367305 2012-11-07 13:49:55Z $ ++ * $Id: wl_android.h 367273 2012-11-07 09:58:55Z $ + */ + + #include +@@ -32,8 +32,6 @@ + * automatically + */ + +- +- + /** + * Android platform dependent functions, feel free to add Android specific functions here + * (save the macros in dhd). Please do NOT declare functions that are NOT exposed to dhd +@@ -51,6 +49,69 @@ int wl_android_wifi_on(struct net_device + int wl_android_wifi_off(struct net_device *dev); + int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd); + ++#define BSSCACHE ++#define RSSIAVG ++#define RSSIOFFSET ++//#define RSSIOFFSET_NEW ++ ++#if defined(RSSIAVG) ++#define RSSIAVG_LEN 8 ++#define RSSICACHE_LEN 8 ++ ++typedef struct wl_rssi_cache { ++ struct wl_rssi_cache *next; ++ int dirty; ++ struct ether_addr BSSID; ++ int16 RSSI[RSSIAVG_LEN]; ++} wl_rssi_cache_t; ++ ++typedef struct wl_rssi_cache_ctrl { ++ wl_rssi_cache_t *m_cache_head; ++} wl_rssi_cache_ctrl_t; ++ ++void wl_free_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl); ++void wl_delete_dirty_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl); ++void wl_reset_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl); ++void wl_update_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, wl_scan_results_t *ss_list); ++void wl_update_connected_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, struct net_device *net); ++int16 wl_get_avg_rssi(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, void *addr); ++#endif ++ ++#if defined(RSSIOFFSET) ++#define RSSI_OFFSET 5 ++#define RSSI_MAX -80 ++#define RSSI_MIN -94 ++#define RSSI_INT ((RSSI_MAX-RSSI_MIN)/RSSI_OFFSET) ++#define BCM4330_CHIP_ID 0x4330 ++#define BCM4330B2_CHIP_REV 4 ++int wl_update_rssi_offset(int rssi); ++#endif ++ ++#if defined(BSSCACHE) ++#define BSSCACHE_LEN 8 ++#define BSSCACHE_TIME 15000 ++ ++typedef struct wl_bss_cache { ++ struct wl_bss_cache *next; ++ int dirty; ++ wl_scan_results_t results; ++} wl_bss_cache_t; ++ ++typedef struct wl_bss_cache_ctrl { ++ wl_bss_cache_t *m_cache_head; ++ struct timer_list *m_timer; ++ int m_timer_expired; ++} wl_bss_cache_ctrl_t; ++ ++void wl_free_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl); ++void wl_delete_dirty_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl); ++void wl_reset_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl); ++void wl_update_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl, wl_scan_results_t *ss_list); ++void wl_run_bss_cache_timer(wl_bss_cache_ctrl_t *bss_cache_ctrl, int kick_off); ++void wl_release_bss_cache_ctrl(wl_bss_cache_ctrl_t *bss_cache_ctrl); ++void wl_init_bss_cache_ctrl(wl_bss_cache_ctrl_t *bss_cache_ctrl); ++#endif ++ + #if defined(CONFIG_WIFI_CONTROL_FUNC) + int wl_android_wifictrl_func_add(void); + void wl_android_wifictrl_func_del(void); +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/wl_cfg80211.c linux-sunxi-new/drivers/net/wireless/bcmdhd/wl_cfg80211.c +--- linux-sunxi/drivers/net/wireless/bcmdhd/wl_cfg80211.c 2014-01-27 01:30:30.100433249 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/wl_cfg80211.c 2014-02-15 00:43:44.791014047 +0100 +@@ -1,7 +1,7 @@ + /* + * Linux cfg80211 driver + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -21,8 +21,9 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: wl_cfg80211.c 419844 2013-08-23 00:07:03Z $ ++ * $Id: wl_cfg80211.c 374275 2012-12-12 11:44:18Z $ + */ ++ + #include + #include + #include +@@ -41,9 +42,6 @@ + #include + #include + #include +-#ifdef PNO_SUPPORT +-#include +-#endif /* PNO_SUPPORT */ + + #include + #include +@@ -56,7 +54,6 @@ + #include + #include + #include +- + #include + #include + #include +@@ -66,15 +63,44 @@ + #ifdef PROP_TXSTATUS + #include + #endif ++#ifdef BCMWAPI_WPI ++/* these items should evetually go into wireless.h of the linux system headfile dir */ ++#ifndef IW_ENCODE_ALG_SM4 ++#define IW_ENCODE_ALG_SM4 0x20 ++#endif ++ ++#ifndef IW_AUTH_WAPI_ENABLED ++#define IW_AUTH_WAPI_ENABLED 0x20 ++#endif ++ ++#ifndef IW_AUTH_WAPI_VERSION_1 ++#define IW_AUTH_WAPI_VERSION_1 0x00000008 ++#endif ++ ++#ifndef IW_AUTH_CIPHER_SMS4 ++#define IW_AUTH_CIPHER_SMS4 0x00000020 ++#endif ++ ++#ifndef IW_AUTH_KEY_MGMT_WAPI_PSK ++#define IW_AUTH_KEY_MGMT_WAPI_PSK 4 ++#endif ++ ++#ifndef IW_AUTH_KEY_MGMT_WAPI_CERT ++#define IW_AUTH_KEY_MGMT_WAPI_CERT 8 ++#endif ++#endif /* BCMWAPI_WPI */ + ++#ifdef BCMWAPI_WPI ++#define IW_WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED | SMS4_ENABLED)) ++#else /* BCMWAPI_WPI */ ++#define IW_WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED)) ++#endif /* BCMWAPI_WPI */ + #ifdef WL11U +-#if !defined(WL_ENABLE_P2P_IF) && !defined(WL_CFG80211_P2P_DEV_IF) +-#error You should enable 'WL_ENABLE_P2P_IF' or 'WL_CFG80211_P2P_DEV_IF' \ +- according to Kernel version and is supported only in Android-JB +-#endif /* !WL_ENABLE_P2P_IF && !WL_CFG80211_P2P_DEV_IF */ ++#ifndef WL_ENABLE_P2P_IF ++#error "You should enable WL_ENABLE_P2P_IF and Only supported in JB" ++#endif + #endif /* WL11U */ + +- + #define IW_WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED)) + + static struct device *cfg80211_parent_dev = NULL; +@@ -85,16 +111,15 @@ u32 wl_dbg_level = WL_DBG_ERR; + + #ifdef VSDB + /* sleep time to keep STA's connecting or connection for continuous af tx or finding a peer */ +-#define DEFAULT_SLEEP_TIME_VSDB 120 ++#define DEFAULT_SLEEP_TIME_VSDB 200 + #define OFF_CHAN_TIME_THRESHOLD_MS 200 +-#define AF_RETRY_DELAY_TIME 40 + + /* if sta is connected or connecting, sleep for a while before retry af tx or finding a peer */ + #define WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(wl) \ + do { \ + if (wl_get_drv_status(wl, CONNECTED, wl_to_prmry_ndev(wl)) || \ + wl_get_drv_status(wl, CONNECTING, wl_to_prmry_ndev(wl))) { \ +- OSL_SLEEP(DEFAULT_SLEEP_TIME_VSDB); \ ++ msleep(DEFAULT_SLEEP_TIME_VSDB); \ + } \ + } while (0) + #else /* VSDB */ +@@ -143,69 +168,6 @@ static const struct ieee80211_regdomain + REG_RULE(5470-10, 5850+10, 40, 6, 20, 0), } + }; + +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \ +- (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF)) +-/* +- * Possible interface combinations supported by driver +- * +- * ADHOC Mode - #ADHOC <= 1 on channels = 1 +- * SoftAP Mode - #AP <= 1 on channels = 1 +- * STA + P2P Mode - #STA <= 2, #{P2P-GO, P2P-client} <= 1, #P2P-device <= 1 +- * on channels = 2 +- */ +-static const struct ieee80211_iface_limit softap_limits[] = { +- { +- .max = 1, +- .types = BIT(NL80211_IFTYPE_AP), +- }, +-}; +- +-static const struct ieee80211_iface_limit sta_p2p_limits[] = { +- /* +- * During P2P-GO removal, P2P-GO is first changed to STA and later only +- * removed. So setting maximum possible number of STA interfaces as 2 to +- * accommodate the above behaviour. +- */ +- { +- .max = 2, +- .types = BIT(NL80211_IFTYPE_STATION), +- }, +- { +- .max = 2, +- .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT), +- }, +-#if defined(WL_CFG80211_P2P_DEV_IF) +- { +- .max = 1, +- .types = BIT(NL80211_IFTYPE_P2P_DEVICE), +- }, +-#endif /* WL_CFG80211_P2P_DEV_IF */ +- { +- .max = 1, +- .types = BIT(NL80211_IFTYPE_ADHOC), +- }, +-}; +- +-static const struct ieee80211_iface_combination +-softap_iface_combinations[] = { +- { +- .num_different_channels = 1, +- .max_interfaces = 1, +- .limits = softap_limits, +- .n_limits = ARRAY_SIZE(softap_limits), +- }, +-}; +- +-static const struct ieee80211_iface_combination +-sta_p2p_iface_combinations[] = { +- { +- .num_different_channels = 2, +- .max_interfaces = 3, +- .limits = sta_p2p_limits, +- .n_limits = ARRAY_SIZE(sta_p2p_limits), +- }, +-}; +-#endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */ + + /* Data Element Definitions */ + #define WPS_ID_CONFIG_METHODS 0x1008 +@@ -242,20 +204,6 @@ sta_p2p_iface_combinations[] = { + + #define PM_BLOCK 1 + #define PM_ENABLE 0 +- +- +- +-#ifndef RSSI_OFFSET +-#define RSSI_OFFSET 0 +-#endif +- +-#ifndef IBSS_COALESCE_ALLOWED +-#define IBSS_COALESCE_ALLOWED 0 +-#endif +- +-#ifndef IBSS_INITIAL_SCAN_ALLOWED +-#define IBSS_INITIAL_SCAN_ALLOWED 0 +-#endif + /* + * cfg80211_ops api/callback list + */ +@@ -265,14 +213,8 @@ static s32 wl_frame_get_mgmt(u16 fc, con + static s32 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, + struct cfg80211_scan_request *request, + struct cfg80211_ssid *this_ssid); +-#if defined(WL_CFG80211_P2P_DEV_IF) +-static s32 +-wl_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request); +-#else +-static s32 +-wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, ++static s32 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, + struct cfg80211_scan_request *request); +-#endif /* WL_CFG80211_P2P_DEV_IF */ + 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); +@@ -288,21 +230,10 @@ static int wl_cfg80211_connect(struct wi + struct cfg80211_connect_params *sme); + static s32 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, + u16 reason_code); +-#if defined(WL_CFG80211_P2P_DEV_IF) +-static s32 +-wl_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, +- enum nl80211_tx_power_setting type, s32 mbm); +-#else +-static s32 +-wl_cfg80211_set_tx_power(struct wiphy *wiphy, +- enum nl80211_tx_power_setting type, s32 dbm); +-#endif /* WL_CFG80211_P2P_DEV_IF */ +-#if defined(WL_CFG80211_P2P_DEV_IF) +-static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, +- struct wireless_dev *wdev, s32 *dbm); +-#else ++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); +-#endif /* WL_CFG80211_P2P_DEV_IF */ + static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy, + struct net_device *dev, + u8 key_idx, bool unicast, bool multicast); +@@ -318,10 +249,13 @@ static s32 wl_cfg80211_get_key(struct wi + 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); ++#if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \ ++ 2, 0)) + static s32 wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, +- bcm_struct_cfgdev *cfgdev, u64 cookie); ++ struct net_device *dev, u64 cookie); + static s32 wl_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *ndev, u8* mac_addr); ++#endif + #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39) + static s32 wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow); + #else +@@ -333,15 +267,8 @@ static s32 wl_cfg80211_del_pmksa(struct + struct cfg80211_pmksa *pmksa); + static s32 wl_cfg80211_flush_pmksa(struct wiphy *wiphy, + struct net_device *dev); +-static void wl_cfg80211_scan_abort(struct wl_priv *wl); + static s32 wl_notify_escan_complete(struct wl_priv *wl, + struct net_device *ndev, bool aborted, bool fw_abort); +-#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0) +-static s32 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, +- u8 *peer, enum nl80211_tdls_operation oper); +-#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0) */ +-static int wl_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev); +- + /* + * event & event Q handlers for cfg80211 interfaces + */ +@@ -362,16 +289,18 @@ static void wl_wakeup_event(struct wl_pr + static s32 wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev, + const wl_event_msg_t *e, void *data); + static s32 wl_notify_connect_status(struct wl_priv *wl, +- bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data); ++ struct net_device *ndev, ++ const wl_event_msg_t *e, void *data); + static s32 wl_notify_roaming_status(struct wl_priv *wl, +- bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data); +-static s32 wl_notify_scan_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev, ++ 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, bcm_struct_cfgdev *cfgdev, ++static s32 wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev, + const wl_event_msg_t *e, void *data); + #ifdef WL_SCHED_SCAN + static s32 +@@ -379,16 +308,11 @@ wl_notify_sched_scan_results(struct wl_p + const wl_event_msg_t *e, void *data); + #endif /* WL_SCHED_SCAN */ + #ifdef PNO_SUPPORT +-static s32 wl_notify_pfn_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev, ++static s32 wl_notify_pfn_status(struct wl_priv *wl, struct net_device *ndev, + const wl_event_msg_t *e, void *data); + #endif /* PNO_SUPPORT */ + static s32 wl_notifier_change_state(struct wl_priv *wl, struct net_info *_net_info, + enum wl_status state, bool set); +- +-#ifdef WLTDLS +-static s32 wl_tdls_event_handler(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev, +- const wl_event_msg_t *e, void *data); +-#endif /* WLTDLS */ + /* + * register/deregister parent device + */ +@@ -426,6 +350,10 @@ static s32 wl_set_key_mgmt(struct net_de + struct cfg80211_connect_params *sme); + static s32 wl_set_set_sharedkey(struct net_device *dev, + struct cfg80211_connect_params *sme); ++#ifdef BCMWAPI_WPI ++static s32 wl_set_set_wapi_ie(struct net_device *dev, ++ struct cfg80211_connect_params *sme); ++#endif + static s32 wl_get_assoc_ies(struct wl_priv *wl, struct net_device *ndev); + static void wl_ch_to_chanspec(int ch, + struct wl_join_params *join_params, size_t *join_params_size); +@@ -435,7 +363,6 @@ static void wl_ch_to_chanspec(int ch, + */ + static void wl_rst_ie(struct wl_priv *wl); + static __used s32 wl_add_ie(struct wl_priv *wl, u8 t, u8 l, u8 *v); +-static void wl_update_hidden_ap_ie(struct wl_bss_info *bi, u8 *ie_stream, u32 *ie_size); + static s32 wl_mrg_ie(struct wl_priv *wl, u8 *ie_stream, u16 ie_size); + static s32 wl_cp_ie(struct wl_priv *wl, u8 *dst, u16 dst_size); + static u32 wl_get_ielen(struct wl_priv *wl); +@@ -448,21 +375,22 @@ wl_cfg80211_add_iw_ie(struct wl_priv *wl + uint8 ie_id, uint8 *data, uint8 data_len); + #endif /* WL11U */ + +-static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *dev, void *data); ++static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *dev); + static void wl_free_wdev(struct wl_priv *wl); +-#ifdef CONFIG_CFG80211_INTERNAL_REGDB + static int + wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request); +-#endif /* CONFIG_CFG80211_INTERNAL_REGDB */ + + 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, struct net_device *ndev); ++static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi, u8 is_roam_done); ++static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev, u8 is_roam_done); + static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy); + s32 wl_cfg80211_channel_to_freq(u32 channel); + +- ++#if defined(DHCP_SCAN_SUPPRESS) + static void wl_cfg80211_work_handler(struct work_struct *work); ++static void wl_cfg80211_scan_supp_timerfunc(ulong data); ++#endif /* DHCP_SCAN_SUPPRESS */ ++ + static s32 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev, + u8 key_idx, const u8 *mac_addr, + struct key_params *params); +@@ -530,14 +458,10 @@ static __used u32 wl_find_msb(u16 bit16) + */ + static int wl_setup_rfkill(struct wl_priv *wl, bool setup); + static int wl_rfkill_set(void *data, bool blocked); +-#ifdef DEBUGFS_CFG80211 +-static s32 wl_setup_debugfs(struct wl_priv *wl); +-static s32 wl_free_debugfs(struct wl_priv *wl); +-#endif + + static wl_scan_params_t *wl_cfg80211_scan_alloc_params(int channel, + int nprobes, int *out_params_size); +-static bool check_dev_role_integrity(struct wl_priv *wl, u32 dev_role); ++static void get_primary_mac(struct wl_priv *wl, struct ether_addr *mac); + + /* + * Some external functions, TODO: move them to dhd_linux.h +@@ -550,10 +474,10 @@ int dhd_start_xmit(struct sk_buff *skb, + + + +-#define RETURN_EIO_IF_NOT_UP(wlpriv) \ ++#define CHECK_SYS_UP(wlpriv) \ + do { \ +- struct net_device *checkSysUpNDev = wl_to_prmry_ndev(wlpriv); \ +- if (unlikely(!wl_get_drv_status(wlpriv, READY, checkSysUpNDev))) { \ ++ struct net_device *ndev = wl_to_prmry_ndev(wlpriv); \ ++ if (unlikely(!wl_get_drv_status(wlpriv, READY, ndev))) { \ + WL_INFO(("device is not ready\n")); \ + return -EIO; \ + } \ +@@ -572,7 +496,6 @@ extern int dhd_wlfc_init(dhd_pub_t *dhd) + extern void dhd_wlfc_deinit(dhd_pub_t *dhd); + #endif /* PROP_TXSTATUS_VSDB */ + +- + #if (WL_DBG_LEVEL > 0) + #define WL_DBG_ESTR_MAX 50 + static s8 wl_dbg_estr[][WL_DBG_ESTR_MAX] = { +@@ -629,18 +552,18 @@ static s8 wl_dbg_estr[][WL_DBG_ESTR_MAX] + } + + static struct ieee80211_rate __wl_rates[] = { +- RATETAB_ENT(DOT11_RATE_1M, 0), +- RATETAB_ENT(DOT11_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE), +- RATETAB_ENT(DOT11_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE), +- RATETAB_ENT(DOT11_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE), +- RATETAB_ENT(DOT11_RATE_6M, 0), +- RATETAB_ENT(DOT11_RATE_9M, 0), +- RATETAB_ENT(DOT11_RATE_12M, 0), +- RATETAB_ENT(DOT11_RATE_18M, 0), +- RATETAB_ENT(DOT11_RATE_24M, 0), +- RATETAB_ENT(DOT11_RATE_36M, 0), +- RATETAB_ENT(DOT11_RATE_48M, 0), +- RATETAB_ENT(DOT11_RATE_54M, 0) ++ 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) +@@ -704,29 +627,14 @@ static const u32 __wl_cipher_suites[] = + WLAN_CIPHER_SUITE_TKIP, + WLAN_CIPHER_SUITE_CCMP, + WLAN_CIPHER_SUITE_AES_CMAC, ++#ifdef BCMWAPI_WPI ++ WLAN_CIPHER_SUITE_SMS4 ++#endif + }; + + +-#if defined(USE_DYNAMIC_MAXPKT_RXGLOM) +-static int maxrxpktglom = 0; +-#endif +- + /* IOCtl version read from targeted driver */ + static int ioctl_version; +-#ifdef DEBUGFS_CFG80211 +-#define S_SUBLOGLEVEL 20 +-static const struct { +- u32 log_level; +- char *sublogname; +-} sublogname_map[] = { +- {WL_DBG_ERR, "ERR"}, +- {WL_DBG_INFO, "INFO"}, +- {WL_DBG_DBG, "DBG"}, +- {WL_DBG_SCAN, "SCAN"}, +- {WL_DBG_TRACE, "TRACE"}, +- {WL_DBG_P2P_ACTION, "P2PACTION"} +-}; +-#endif + + /* Return a new chanspec given a legacy chanspec + * Returns INVCHANSPEC on error +@@ -918,14 +826,7 @@ wl_cfg80211_default_mgmt_stypes[NUM_NL80 + BIT(IEEE80211_STYPE_AUTH >> 4) | + BIT(IEEE80211_STYPE_DEAUTH >> 4) | + BIT(IEEE80211_STYPE_ACTION >> 4) +- }, +-#if defined(WL_CFG80211_P2P_DEV_IF) +- [NL80211_IFTYPE_P2P_DEVICE] = { +- .tx = 0xffff, +- .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | +- BIT(IEEE80211_STYPE_PROBE_REQ >> 4) +- }, +-#endif /* WL_CFG80211_P2P_DEV_IF */ ++ } + }; + + static void swap_key_from_BE(struct wl_wsec_key *key) +@@ -1064,16 +965,14 @@ static chanspec_t wl_cfg80211_get_shared + else { + bss = (struct wl_bss_info *) (wl->extra_buf + 4); + chspec = bss->chanspec; +- + WL_DBG(("Valid BSS Found. chanspec:%d \n", chspec)); + } + return chspec; + } + +-static bcm_struct_cfgdev * +-wl_cfg80211_add_monitor_if(char *name) ++static struct net_device* wl_cfg80211_add_monitor_if(char *name) + { +-#if defined(WL_ENABLE_P2P_IF) || defined(WL_CFG80211_P2P_DEV_IF) ++#if defined(WLP2P) && defined(WL_ENABLE_P2P_IF) + WL_INFO(("wl_cfg80211_add_monitor_if: No more support monitor interface\n")); + return ERR_PTR(-EOPNOTSUPP); + #else +@@ -1081,17 +980,12 @@ wl_cfg80211_add_monitor_if(char *name) + + dhd_add_monitor(name, &ndev); + WL_INFO(("wl_cfg80211_add_monitor_if net device returned: 0x%p\n", ndev)); +- return ndev_to_cfgdev(ndev); +-#endif /* WL_ENABLE_P2P_IF || WL_CFG80211_P2P_DEV_IF */ ++ return ndev; ++#endif /* defined(WLP2P) && defined(WL_ENABLE_P2P_IF) */ + } + +-static bcm_struct_cfgdev * +-wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, +-#if defined(WL_CFG80211_P2P_DEV_IF) +- const char *name, +-#else +- char *name, +-#endif /* WL_CFG80211_P2P_DEV_IF */ ++static struct net_device * ++wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, + enum nl80211_iftype type, u32 *flags, + struct vif_params *params) + { +@@ -1134,10 +1028,6 @@ wl_cfg80211_add_virtual_iface(struct wip + return NULL; + case NL80211_IFTYPE_MONITOR: + return wl_cfg80211_add_monitor_if(name); +-#if defined(WL_CFG80211_P2P_DEV_IF) +- case NL80211_IFTYPE_P2P_DEVICE: +- return wl_cfgp2p_add_p2p_disc_if(); +-#endif /* WL_CFG80211_P2P_DEV_IF */ + case NL80211_IFTYPE_P2P_CLIENT: + case NL80211_IFTYPE_STATION: + wlif_type = WL_P2P_IF_CLIENT; +@@ -1159,7 +1049,6 @@ wl_cfg80211_add_virtual_iface(struct wip + return NULL; + } + if (wl->p2p_supported && (wlif_type != -1)) { +- ASSERT(wl->p2p); /* ensure expectation of p2p initialization */ + if (wl_get_p2p_status(wl, IF_DELETING)) { + /* wait till IF_DEL is complete + * release the lock for the unregister to proceed +@@ -1168,7 +1057,8 @@ wl_cfg80211_add_virtual_iface(struct wip + rtnl_unlock(); + rollback_lock = true; + } +- WL_INFO(("Released the lock and wait till IF_DEL is complete\n")); ++ WL_INFO(("%s: Released the lock and wait till IF_DEL is complete\n", ++ __func__)); + timeout = wait_event_interruptible_timeout(wl->netif_change_event, + (wl_get_p2p_status(wl, IF_DELETING) == false), + msecs_to_jiffies(MAX_WAIT_TIME)); +@@ -1211,7 +1101,7 @@ wl_cfg80211_add_virtual_iface(struct wip + memset(wl->p2p->vir_ifname, 0, IFNAMSIZ); + strncpy(wl->p2p->vir_ifname, name, IFNAMSIZ - 1); + +- wl_cfg80211_scan_abort(wl); ++ wl_notify_escan_complete(wl, _ndev, true, true); + #ifdef PROP_TXSTATUS_VSDB + if (!wl->wlfc_on && !disable_proptx) { + dhd->wlfc_enabled = true; +@@ -1274,10 +1164,6 @@ wl_cfg80211_add_virtual_iface(struct wip + val = 1; + /* Disable firmware roaming for P2P interface */ + wldev_iovar_setint(_ndev, "roam_off", val); +- +- if (mode != WL_MODE_AP) +- wldev_iovar_setint(_ndev, "buf_key_b4_m4", 1); +- + WL_ERR((" virtual interface(%s) is " + "created net attach done\n", wl->p2p->vir_ifname)); + if (mode == WL_MODE_AP) +@@ -1287,12 +1173,6 @@ wl_cfg80211_add_virtual_iface(struct wip + else if (type == NL80211_IFTYPE_P2P_GO) + dhd_mode = DHD_FLAG_P2P_GO_MODE; + DNGL_FUNC(dhd_cfg80211_set_p2p_info, (wl, dhd_mode)); +-#ifdef PROP_TXSTATUS_VSDB +- if (dhd->plat_enable) +- dhd->plat_enable((void *)dhd); +-#endif /* PROP_TXSTATUS_VSDB */ +- /* reinitialize completion to clear previous count */ +- INIT_COMPLETION(wl->iface_disable); + } else { + /* put back the rtnl_lock again */ + if (rollback_lock) +@@ -1302,7 +1182,8 @@ wl_cfg80211_add_virtual_iface(struct wip + /* put back the rtnl_lock again */ + if (rollback_lock) + rtnl_lock(); +- return ndev_to_cfgdev(_ndev); ++ return _ndev; ++ + } else { + wl_clr_p2p_status(wl, IF_ADD); + WL_ERR((" virtual interface(%s) is not created \n", wl->p2p->vir_ifname)); +@@ -1312,8 +1193,6 @@ wl_cfg80211_add_virtual_iface(struct wip + if (dhd->wlfc_enabled && wl->wlfc_on) { + dhd->wlfc_enabled = false; + dhd_wlfc_deinit(dhd); +- if (dhd->plat_deinit) +- dhd->plat_deinit((void *)dhd); + wl->wlfc_on = false; + } + #endif /* PROP_TXSTATUS_VSDB */ +@@ -1326,27 +1205,21 @@ fail: + } + + static s32 +-wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev) ++wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev) + { +- struct net_device *dev = NULL; + struct ether_addr p2p_mac; + struct wl_priv *wl = wiphy_priv(wiphy); + s32 timeout = -1; + s32 ret = 0; +- s32 index = -1; + WL_DBG(("Enter\n")); + +-#if defined(WL_CFG80211_P2P_DEV_IF) +- if (cfgdev->iftype == NL80211_IFTYPE_P2P_DEVICE) { +- return wl_cfgp2p_del_p2p_disc_if(cfgdev); ++ if (wl->p2p_net == dev) { ++ /* Since there is no ifidx corresponding to p2p0, cmds to ++ * firmware should be routed through primary I/F ++ */ ++ dev = wl_to_prmry_ndev(wl); + } +-#endif /* WL_CFG80211_P2P_DEV_IF */ +- dev = cfgdev_to_wlc_ndev(cfgdev, wl); + +- if (wl_cfgp2p_find_idx(wl, dev, &index) != BCME_OK) { +- WL_ERR(("Find p2p index from ndev(%p) failed\n", dev)); +- return BCME_ERROR; +- } + if (wl->p2p_supported) { + memcpy(p2p_mac.octet, wl->p2p->int_addr.octet, ETHER_ADDR_LEN); + +@@ -1360,11 +1233,6 @@ wl_cfg80211_del_virtual_iface(struct wip + } + wldev_iovar_setint(dev, "mpc", 1); + +- if (wl->pm_enable_work_on) { +- cancel_delayed_work_sync(&wl->pm_enable_work); +- wl->pm_enable_work_on = false; +- } +- + /* for GC */ + if (wl_get_drv_status(wl, DISCONNECTING, dev) && + (wl_get_mode_by_netdev(wl, dev) != WL_MODE_AP)) { +@@ -1387,13 +1255,11 @@ wl_cfg80211_del_virtual_iface(struct wip + WL_ERR(("Wait for Link Down event for GO !!!\n")); + wait_for_completion_timeout(&wl->iface_disable, + msecs_to_jiffies(500)); ++ } else { ++ msleep(300); + } + } +- wl_cfgp2p_clear_management_ie(wl, index); +- +- if (wl_get_mode_by_netdev(wl, dev) != WL_MODE_AP) +- wldev_iovar_setint(dev, "buf_key_b4_m4", 0); +- ++ wl_cfgp2p_clear_management_ie(wl, wl_cfgp2p_find_idx(wl, dev)); + /* delete interface after link down */ + ret = wl_cfgp2p_ifdel(wl, &p2p_mac); + /* Firmware could not delete the interface so we will not get WLC_E_IF +@@ -1419,9 +1285,6 @@ wl_cfg80211_del_virtual_iface(struct wip + WL_ERR(("IFDEL didn't complete properly\n")); + } + ret = dhd_del_monitor(dev); +- if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_AP) { +- DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_CANCEL((dhd_pub_t *)(wl->pub)); +- } + } + } + return ret; +@@ -1434,10 +1297,8 @@ wl_cfg80211_change_virtual_iface(struct + { + s32 ap = 0; + s32 infra = 0; +- s32 ibss = 0; + s32 wlif_type; + s32 mode = 0; +- s32 err = BCME_OK; + chanspec_t chspec; + struct wl_priv *wl = wiphy_priv(wiphy); + dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); +@@ -1452,7 +1313,6 @@ wl_cfg80211_change_virtual_iface(struct + break; + case NL80211_IFTYPE_ADHOC: + mode = WL_MODE_IBSS; +- ibss = 1; + break; + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_P2P_CLIENT: +@@ -1516,16 +1376,6 @@ wl_cfg80211_change_virtual_iface(struct + WL_DBG(("Change_virtual_iface for transition from GO/AP to client/STA")); + } + +- if (ibss) { +- infra = 0; +- wl_set_mode_by_netdev(wl, ndev, mode); +- err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(s32), true); +- if (err < 0) { +- WL_ERR(("SET Adhoc error %d\n", err)); +- return -EINVAL; +- } +- } +- + ndev->ieee80211_ptr->iftype = type; + return 0; + } +@@ -1575,9 +1425,7 @@ wl_cfg80211_ifdel_ops(struct net_device + { + struct wl_priv *wl = wlcfg_drv_priv; + bool rollback_lock = false; +- s32 type = -1; +- s32 bssidx = -1; +- ++ s32 index = 0; + #ifdef PROP_TXSTATUS_VSDB + dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); + #endif /* PROP_TXSTATUS_VSDB */ +@@ -1601,29 +1449,20 @@ wl_cfg80211_ifdel_ops(struct net_device + if (rollback_lock) + rtnl_unlock(); + } +- WL_ERR(("IF_DEL event called from dongle, net %p, vif name: %s\n", +- ndev, wl->p2p->vir_ifname)); ++ WL_ERR(("IF_DEL event called from dongle, net %x, vif name: %s\n", ++ (unsigned int)ndev, wl->p2p->vir_ifname)); + + memset(wl->p2p->vir_ifname, '\0', IFNAMSIZ); +- if (wl_cfgp2p_find_idx(wl, ndev, &bssidx) != BCME_OK) { +- WL_ERR(("Find p2p bssidx from ndev(%p) failed\n", ndev)); +- return BCME_ERROR; +- } +- if (wl_cfgp2p_find_type(wl, bssidx, &type) != BCME_OK) { +- WL_ERR(("Find p2p type from bssidx(%d) failed\n", bssidx)); +- return BCME_ERROR; +- } +- wl_to_p2p_bss_ndev(wl, type) = NULL; +- wl_to_p2p_bss_bssidx(wl, type) = WL_INVALID; ++ index = wl_cfgp2p_find_idx(wl, ndev); ++ wl_to_p2p_bss_ndev(wl, index) = NULL; ++ wl_to_p2p_bss_bssidx(wl, index) = WL_INVALID; + wl->p2p->vif_created = false; + +- WL_DBG(("type : %d\n", type)); ++ WL_DBG(("index : %d\n", index)); + #ifdef PROP_TXSTATUS_VSDB + if (dhd->wlfc_enabled && wl->wlfc_on) { + dhd->wlfc_enabled = false; + dhd_wlfc_deinit(dhd); +- if (dhd->plat_deinit) +- dhd->plat_deinit((void *)dhd); + wl->wlfc_on = false; + } + #endif /* PROP_TXSTATUS_VSDB */ +@@ -1669,14 +1508,13 @@ wl_cfg80211_notify_ifchange(void) + + /* Find listen channel */ + static s32 wl_find_listen_channel(struct wl_priv *wl, +- const u8 *ie, u32 ie_len) ++ u8 *ie, u32 ie_len) + { + wifi_p2p_ie_t *p2p_ie; + u8 *end, *pos; + s32 listen_channel; + +- pos = (u8 *)ie; +- p2p_ie = wl_cfgp2p_find_p2pie(pos, ie_len); ++ p2p_ie = wl_cfgp2p_find_p2pie(ie, ie_len); + + if (p2p_ie == NULL) + return 0; +@@ -1776,8 +1614,20 @@ static void wl_scan_prep(struct wl_scan_ + continue; + + if (request->channels[i]->band == IEEE80211_BAND_2GHZ) { ++#ifdef WL_HOST_BAND_MGMT ++ if (wl->curr_band == WLC_BAND_5G) { ++ WL_DBG(("In 5G only mode, omit 2G channel:%d\n", channel)); ++ continue; ++ } ++#endif /* WL_HOST_BAND_MGMT */ + chanspec |= WL_CHANSPEC_BAND_2G; + } else { ++#ifdef WL_HOST_BAND_MGMT ++ if (wl->curr_band == WLC_BAND_2G) { ++ WL_DBG(("In 2G only mode, omit 5G channel:%d\n", channel)); ++ continue; ++ } ++#endif /* WL_HOST_BAND_MGMT */ + chanspec |= WL_CHANSPEC_BAND_5G; + } + +@@ -1822,9 +1672,8 @@ static void wl_scan_prep(struct wl_scan_ + htod32((n_ssids << WL_SCAN_PARAMS_NSSID_SHIFT) | + (n_channels & WL_SCAN_PARAMS_COUNT_MASK)); + +- if (n_channels == 1) { +- params->active_time = htod32(WL_SCAN_CONNECT_DWELL_TIME_MS); +- params->nprobes = htod32(params->active_time / WL_SCAN_JOIN_PROBE_INTERVAL_MS); ++ if (n_channels == 1 && wl_get_drv_status_all(wl, CONNECTED)) { ++ params->active_time = WL_SCAN_CONNECT_DWELL_TIME_MS; + } + } + +@@ -1926,7 +1775,6 @@ wl_get_valid_channels(struct net_device + return err; + } + +- + static s32 + wl_run_escan(struct wl_priv *wl, struct net_device *ndev, + struct cfg80211_scan_request *request, uint16 action) +@@ -1945,11 +1793,9 @@ wl_run_escan(struct wl_priv *wl, struct + u16 *default_chan_list = NULL; + wl_uint32_list_t *list; + struct net_device *dev = NULL; +- p2p_scan_purpose_t p2p_scan_purpose = P2P_SCAN_PURPOSE_MIN; + + WL_DBG(("Enter \n")); + +- /* scan request can come with empty request : perform all default scan */ + if (!wl) { + err = -EINVAL; + goto exit; +@@ -1977,11 +1823,12 @@ wl_run_escan(struct wl_priv *wl, struct + err = -ENOMEM; + goto exit; + } ++ + wl_scan_prep(¶ms->params, request); + + params->version = htod32(ESCAN_REQ_VERSION); + params->action = htod16(action); +- wl_escan_set_sync_id(params->sync_id, wl); ++ params->sync_id = htod16(0x1234); + if (params_size + sizeof("escan") >= WLC_IOCTL_MEDLEN) { + WL_ERR(("ioctl buffer length not sufficient\n")); + kfree(params); +@@ -2018,8 +1865,19 @@ wl_run_escan(struct wl_priv *wl, struct + n_valid_chan = dtoh32(list->count); + for (i = 0; i < num_chans; i++) + { ++#ifdef WL_HOST_BAND_MGMT ++ int channel_band = 0; ++#endif /* WL_HOST_BAND_MGMT */ + _freq = request->channels[i]->center_freq; + channel = ieee80211_frequency_to_channel(_freq); ++#ifdef WL_HOST_BAND_MGMT ++ channel_band = (channel > CH_MAX_2G_CHANNEL) ? ++ WLC_BAND_5G : WLC_BAND_2G; ++ if ((wl->curr_band != WLC_BAND_AUTO) && ++ (wl->curr_band != channel_band) && ++ !IS_P2P_SOCIAL_CHANNEL(channel)) ++ continue; ++#endif /* WL_HOST_BAND_MGMT */ + + /* ignore DFS channels */ + if (request->channels[i]->flags & +@@ -2038,13 +1896,12 @@ wl_run_escan(struct wl_priv *wl, struct + + } + } +- if (num_chans == SOCIAL_CHAN_CNT && ( ++ if (num_chans == 3 && ( + (default_chan_list[0] == SOCIAL_CHAN_1) && + (default_chan_list[1] == SOCIAL_CHAN_2) && + (default_chan_list[2] == SOCIAL_CHAN_3))) { + /* SOCIAL CHANNELS 1, 6, 11 */ + search_state = WL_P2P_DISC_ST_SEARCH; +- p2p_scan_purpose = P2P_SCAN_SOCIAL_CHANNEL; + WL_INFO(("P2P SEARCH PHASE START \n")); + } else if ((dev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION)) && + (wl_get_mode_by_netdev(wl, dev) == WL_MODE_AP)) { +@@ -2052,32 +1909,16 @@ wl_run_escan(struct wl_priv *wl, struct + WL_INFO(("Already a GO. Do SEARCH Only")); + search_state = WL_P2P_DISC_ST_SEARCH; + num_chans = n_nodfs; +- p2p_scan_purpose = P2P_SCAN_NORMAL; + +- } else if (num_chans == 1) { +- p2p_scan_purpose = P2P_SCAN_CONNECT_TRY; +- } else if (num_chans == SOCIAL_CHAN_CNT + 1) { +- /* SOCIAL_CHAN_CNT + 1 takes care of the Progressive scan supported by +- * the supplicant +- */ +- p2p_scan_purpose = P2P_SCAN_SOCIAL_CHANNEL; + } else { + WL_INFO(("P2P SCAN STATE START \n")); + num_chans = n_nodfs; +- p2p_scan_purpose = P2P_SCAN_NORMAL; + } +- } else { +- err = -EINVAL; +- goto exit; ++ + } + err = wl_cfgp2p_escan(wl, ndev, wl->active_scan, num_chans, default_chan_list, + search_state, action, +- wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE), NULL, +- p2p_scan_purpose); +- +- if (!err) +- wl->p2p->search_state = search_state; +- ++ wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE)); + kfree(default_chan_list); + } + exit: +@@ -2101,8 +1942,7 @@ wl_do_escan(struct wl_priv *wl, struct w + wl_scan_results_t *results; + WL_SCAN(("Enter \n")); + mutex_lock(&wl->usr_sync); +- +- results = wl_escan_get_buf(wl, FALSE); ++ results = (wl_scan_results_t *) wl->escan_info.escan_buf; + results->version = 0; + results->count = 0; + results->buflen = WL_SCAN_RESULTS_FIXED_SIZE; +@@ -2139,6 +1979,7 @@ __wl_cfg80211_scan(struct wiphy *wiphy, + bool p2p_ssid; + #ifdef WL11U + bcm_tlv_t *interworking_ie; ++ u32 ie_len; + #endif + s32 err = 0; + s32 bssidx = -1; +@@ -2147,16 +1988,13 @@ __wl_cfg80211_scan(struct wiphy *wiphy, + unsigned long flags; + static s32 busy_count = 0; + +- dhd_pub_t *dhd; +- +- dhd = (dhd_pub_t *)(wl->pub); +- if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) { +- WL_ERR(("Invalid Scan Command at SoftAP mode\n")); +- return -EINVAL; ++ /* If scan req comes for p2p0, send it over primary I/F ++ * Scan results will be delivered corresponding to cfg80211_scan_request ++ */ ++ if (ndev == wl->p2p_net) { ++ ndev = wl_to_prmry_ndev(wl); + } + +- ndev = ndev_to_wlc_ndev(ndev, wl); +- + if (WL_DRV_STATUS_SENDING_AF_FRM_EXT(wl)) { + WL_ERR(("Sending Action Frames. Try it again.\n")); + return -EAGAIN; +@@ -2241,16 +2079,13 @@ __wl_cfg80211_scan(struct wiphy *wiphy, + } + } + if (!wl->p2p_supported || !p2p_scan(wl)) { ++ bssidx = wl_cfgp2p_find_idx(wl, ndev); + +- if (wl_cfgp2p_find_idx(wl, ndev, &bssidx) != BCME_OK) { +- WL_ERR(("Find p2p index from ndev(%p) failed\n", +- ndev)); +- err = BCME_ERROR; +- goto scan_out; +- } + #ifdef WL11U + if ((interworking_ie = wl_cfg80211_find_interworking_ie( + (u8 *)request->ie, request->ie_len)) != NULL) { ++ ie_len = interworking_ie->len; ++ + err = wl_cfg80211_add_iw_ie(wl, ndev, bssidx, + VNDR_IE_CUSTOM_FLAG, interworking_ie->id, + interworking_ie->data, interworking_ie->len); +@@ -2267,7 +2102,6 @@ __wl_cfg80211_scan(struct wiphy *wiphy, + + wldev_iovar_setint_bsscfg(ndev, "grat_arp", 0, + bssidx); +- wl->wl11u = FALSE; + /* we don't care about error */ + } + #endif /* WL11U */ +@@ -2286,8 +2120,6 @@ __wl_cfg80211_scan(struct wiphy *wiphy, + /* we don't do iscan in ibss */ + ssids = this_ssid; + } +- if (request && !p2p_scan(wl)) +- WL_TRACE_HW4(("START SCAN\n")); + wl->scan_request = request; + wl_set_drv_status(wl, SCANNING, ndev); + if (iscan_req) { +@@ -2302,10 +2134,10 @@ __wl_cfg80211_scan(struct wiphy *wiphy, + + /* find my listen channel */ + wl->afx_hdl->my_listen_chan = +- wl_find_listen_channel(wl, request->ie, ++ wl_find_listen_channel(wl, (u8 *)request->ie, + request->ie_len); + err = wl_cfgp2p_enable_discovery(wl, ndev, +- request->ie, request->ie_len); ++ request->ie, request->ie_len); + + if (unlikely(err)) { + goto scan_out; +@@ -2353,11 +2185,13 @@ __wl_cfg80211_scan(struct wiphy *wiphy, + } + + scan_success: ++ + busy_count = 0; + + return 0; + + scan_out: ++ + if (err == BCME_BUSY || err == BCME_NOTREADY) { + WL_ERR(("Scan err = (%d), busy?%d", err, -EBUSY)); + err = -EBUSY; +@@ -2384,43 +2218,33 @@ scan_out: + if ((ret = wldev_ioctl(ndev, WLC_GET_BSSID, + &bssid, ETHER_ADDR_LEN, false)) == 0) + WL_ERR(("FW is connected with " MACDBG "/n", +- MAC2STRDBG(bssid.octet))); ++ MAC2STRDBG(bssid.octet))); + else + WL_ERR(("GET BSSID failed with %d\n", ret)); + +- wl_cfg80211_scan_abort(wl); ++ wl_cfg80211_disconnect(wiphy, ndev, DOT11_RC_DISASSOC_LEAVING); + } + } else { + busy_count = 0; + } +- + wl_clr_drv_status(wl, SCANNING, ndev); + if (timer_pending(&wl->scan_timeout)) + del_timer_sync(&wl->scan_timeout); + spin_lock_irqsave(&wl->cfgdrv_lock, flags); + wl->scan_request = NULL; + spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); +- + return err; + } + +-#if defined(WL_CFG80211_P2P_DEV_IF) +-static s32 +-wl_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) +-#else + static s32 + wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, + struct cfg80211_scan_request *request) +-#endif /* WL_CFG80211_P2P_DEV_IF */ + { + s32 err = 0; + struct wl_priv *wl = wiphy_priv(wiphy); +-#if defined(WL_CFG80211_P2P_DEV_IF) +- struct net_device *ndev = wl_to_prmry_ndev(wl); +-#endif /* WL_CFG80211_P2P_DEV_IF */ + + WL_DBG(("Enter \n")); +- RETURN_EIO_IF_NOT_UP(wl); ++ CHECK_SYS_UP(wl); + + err = __wl_cfg80211_scan(wiphy, ndev, request, NULL); + if (unlikely(err)) { +@@ -2478,7 +2302,7 @@ static s32 wl_cfg80211_set_wiphy_params( + struct net_device *ndev = wl_to_prmry_ndev(wl); + s32 err = 0; + +- RETURN_EIO_IF_NOT_UP(wl); ++ CHECK_SYS_UP(wl); + WL_DBG(("Enter\n")); + if (changed & WIPHY_PARAM_RTS_THRESHOLD && + (wl->conf->rts_threshold != wiphy->rts_threshold)) { +@@ -2513,149 +2337,6 @@ static s32 wl_cfg80211_set_wiphy_params( + return err; + } + +-static chanspec_t channel_to_chanspec(struct wiphy *wiphy, struct net_device *dev, u32 channel) +-{ +- struct wl_priv *wl = wiphy_priv(wiphy); +- u8 *buf = NULL; +- wl_uint32_list_t *list; +- int err = BCME_OK; +- chanspec_t c = 0, ret_c = 0; +- int bw = 0, tmp_bw = 0; +- int i; +- u32 tmp_c, sb; +- u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL; +-#define LOCAL_BUF_SIZE 1024 +- buf = (u8 *) kzalloc(LOCAL_BUF_SIZE, kflags); +- if (!buf) { +- WL_ERR(("buf memory alloc failed\n")); +- goto exit; +- } +- list = (wl_uint32_list_t *)(void *)buf; +- list->count = htod32(WL_NUMCHANSPECS); +- err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL, +- 0, buf, LOCAL_BUF_SIZE, 0, &wl->ioctl_buf_sync); +- if (err != BCME_OK) { +- WL_ERR(("get chanspecs failed with %d\n", err)); +- goto exit; +- } +- for (i = 0; i < dtoh32(list->count); i++) { +- c = dtoh32(list->element[i]); +- if (channel <= CH_MAX_2G_CHANNEL) { +- if (!CHSPEC_IS20(c)) +- continue; +- if (channel == CHSPEC_CHANNEL(c)) { +- ret_c = c; +- bw = 20; +- goto exit; +- } +- } +- if (CHSPEC_IS20(c)) { +- tmp_c = CHSPEC_CHANNEL(c); +- tmp_bw = 20; +- } +- else if (CHSPEC_IS40(c)) { +- tmp_c = CHSPEC_CHANNEL(c); +- if (CHSPEC_SB_UPPER(c)) { +- tmp_c += CH_10MHZ_APART; +- } else { +- tmp_c -= CH_10MHZ_APART; +- } +- tmp_bw = 40; +- } +- else { +- tmp_c = CHSPEC_CHANNEL(c); +- sb = c & WL_CHANSPEC_CTL_SB_MASK; +- if (sb == WL_CHANSPEC_CTL_SB_LL) { +- tmp_c -= (CH_10MHZ_APART + CH_20MHZ_APART); +- } else if (sb == WL_CHANSPEC_CTL_SB_LU) { +- tmp_c -= CH_10MHZ_APART; +- } else if (sb == WL_CHANSPEC_CTL_SB_UL) { +- tmp_c += CH_10MHZ_APART; +- } else { +- /* WL_CHANSPEC_CTL_SB_UU */ +- tmp_c += (CH_10MHZ_APART + CH_20MHZ_APART); +- } +- tmp_bw = 80; +- } +- if (tmp_c != channel) +- continue; +- +- if (tmp_bw > bw) { +- bw = tmp_bw; +- ret_c = c; +- } +- } +-exit: +- if (buf) +- kfree(buf); +-#undef LOCAL_BUF_SIZE +- WL_INFO(("return chanspec %x %d\n", ret_c, bw)); +- return ret_c; +-} +- +-void +-wl_cfg80211_ibss_vsie_set_buffer(vndr_ie_setbuf_t *ibss_vsie, int ibss_vsie_len) +-{ +- struct wl_priv *wl = wlcfg_drv_priv; +- +- if (wl != NULL && ibss_vsie != NULL) { +- if (wl->ibss_vsie != NULL) { +- kfree(wl->ibss_vsie); +- } +- wl->ibss_vsie = ibss_vsie; +- wl->ibss_vsie_len = ibss_vsie_len; +- } +-} +- +-static void +-wl_cfg80211_ibss_vsie_free(struct wl_priv *wl) +-{ +- /* free & initiralize VSIE (Vendor Specific IE) */ +- if (wl->ibss_vsie != NULL) { +- kfree(wl->ibss_vsie); +- wl->ibss_vsie = NULL; +- wl->ibss_vsie_len = 0; +- } +-} +- +-s32 +-wl_cfg80211_ibss_vsie_delete(struct net_device *dev) +-{ +- struct wl_priv *wl = wlcfg_drv_priv; +- char *ioctl_buf = NULL; +- s32 ret = BCME_OK; +- +- if (wl != NULL && wl->ibss_vsie != NULL) { +- ioctl_buf = kmalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL); +- if (!ioctl_buf) { +- WL_ERR(("ioctl memory alloc failed\n")); +- return -ENOMEM; +- } +- +- /* change the command from "add" to "del" */ +- strncpy(wl->ibss_vsie->cmd, "del", VNDR_IE_CMD_LEN - 1); +- wl->ibss_vsie->cmd[VNDR_IE_CMD_LEN - 1] = '\0'; +- +- ret = wldev_iovar_setbuf(dev, "ie", +- wl->ibss_vsie, wl->ibss_vsie_len, +- ioctl_buf, WLC_IOCTL_MEDLEN, NULL); +- WL_ERR(("ret=%d\n", ret)); +- +- if (ret == BCME_OK) { +- /* free & initiralize VSIE */ +- kfree(wl->ibss_vsie); +- wl->ibss_vsie = NULL; +- wl->ibss_vsie_len = 0; +- } +- +- if (ioctl_buf) { +- kfree(ioctl_buf); +- } +- } +- +- return ret; +-} +- + static s32 + wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_ibss_params *params) +@@ -2667,70 +2348,49 @@ wl_cfg80211_join_ibss(struct wiphy *wiph + struct cfg80211_ssid ssid; + s32 scan_retry = 0; + s32 err = 0; +- int scan_suppress = 1; +- size_t join_params_size; +- chanspec_t chanspec; ++ bool rollback_lock = false; + + WL_TRACE(("In\n")); +- RETURN_EIO_IF_NOT_UP(wl); +- WL_INFO(("JOIN BSSID:" MACDBG "\n", MAC2STRDBG(params->bssid))); +- if (!params->ssid || params->ssid_len <= 0) { +- WL_ERR(("Invalid parameter\n")); +- return -EINVAL; +- } +- if (wl_get_drv_status(wl, CONNECTED, dev)) { +- struct wlc_ssid *ssid = (struct wlc_ssid *)wl_read_prof(wl, dev, WL_PROF_SSID); +- u8 *bssid = (u8 *)wl_read_prof(wl, dev, WL_PROF_BSSID); +- if (!params->bssid || (memcmp(params->bssid, bssid, ETHER_ADDR_LEN) == 0 && +- memcmp(params->ssid, ssid->SSID, ssid->SSID_len) == 0)) { +- WL_ERR(("Connection already existed to " MACDBG "\n", +- MAC2STRDBG((u8 *)wl_read_prof(wl, dev, WL_PROF_BSSID)))); +- return -EISCONN; +- } +- WL_ERR(("Ignore Previous connecton to %s (" MACDBG ")\n", +- ssid->SSID, MAC2STRDBG(bssid))); ++ CHECK_SYS_UP(wl); ++ if (params->bssid) { ++ WL_ERR(("Invalid bssid\n")); ++ return -EOPNOTSUPP; + } +- +- /* remove the VSIE */ +- wl_cfg80211_ibss_vsie_delete(dev); +- + bss = cfg80211_get_ibss(wiphy, NULL, params->ssid, params->ssid_len); + if (!bss) { +- if (IBSS_INITIAL_SCAN_ALLOWED == TRUE) { +- memcpy(ssid.ssid, params->ssid, params->ssid_len); +- ssid.ssid_len = params->ssid_len; +- do { +- if (unlikely +- (__wl_cfg80211_scan(wiphy, dev, NULL, &ssid) == +- -EBUSY)) { +- wl_delay(150); +- } else { +- break; +- } +- } while (++scan_retry < WL_SCAN_RETRY_MAX); +- +- /* wait 4 secons till scan done.... */ +- schedule_timeout_interruptible(msecs_to_jiffies(4000)); +- bss = cfg80211_get_ibss(wiphy, NULL, +- params->ssid, params->ssid_len); ++ memcpy(ssid.ssid, params->ssid, params->ssid_len); ++ ssid.ssid_len = params->ssid_len; ++ do { ++ if (unlikely ++ (__wl_cfg80211_scan(wiphy, dev, NULL, &ssid) == ++ -EBUSY)) { ++ wl_delay(150); ++ } else { ++ break; ++ } ++ } while (++scan_retry < WL_SCAN_RETRY_MAX); ++ /* to allow scan_inform to propagate to cfg80211 plane */ ++ if (rtnl_is_locked()) { ++ rtnl_unlock(); ++ rollback_lock = true; + } ++ ++ /* wait 4 secons till scan done.... */ ++ schedule_timeout_interruptible(msecs_to_jiffies(4000)); ++ if (rollback_lock) ++ rtnl_lock(); ++ bss = cfg80211_get_ibss(wiphy, NULL, ++ params->ssid, params->ssid_len); + } +- if (bss && ((IBSS_COALESCE_ALLOWED == TRUE) || +- ((IBSS_COALESCE_ALLOWED == FALSE) && params->bssid && +- !memcmp(bss->bssid, params->bssid, ETHER_ADDR_LEN)))) { ++ if (bss) { + wl->ibss_starter = false; + WL_DBG(("Found IBSS\n")); + } else { + wl->ibss_starter = true; + } +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) +- chan = params->chandef.chan; +-#else + chan = params->channel; +-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) */ + if (chan) + wl->channel = ieee80211_frequency_to_channel(chan->center_freq); +- chanspec = channel_to_chanspec(wiphy, dev, wl->channel); + /* + * Join with specific BSSID and cached SSID + * If SSID is zero join based on BSSID only +@@ -2739,56 +2399,18 @@ wl_cfg80211_join_ibss(struct wiphy *wiph + memcpy((void *)join_params.ssid.SSID, (void *)params->ssid, + params->ssid_len); + join_params.ssid.SSID_len = htod32(params->ssid_len); +- if (params->bssid) { +- memcpy(&join_params.params.bssid, params->bssid, ETHER_ADDR_LEN); +- err = wldev_ioctl(dev, WLC_SET_DESIRED_BSSID, &join_params.params.bssid, +- ETHER_ADDR_LEN, true); +- if (unlikely(err)) { +- WL_ERR(("Error (%d)\n", err)); +- return err; +- } +- } else ++ if (params->bssid) ++ memcpy(&join_params.params.bssid, params->bssid, ++ ETHER_ADDR_LEN); ++ else + memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN); + +- wldev_iovar_setint(dev, "ibss_coalesce_allowed", IBSS_COALESCE_ALLOWED); +- +- if (IBSS_INITIAL_SCAN_ALLOWED == FALSE) { +- scan_suppress = TRUE; +- /* Set the SCAN SUPRESS Flag in the firmware to skip join scan */ +- err = wldev_ioctl(dev, WLC_SET_SCANSUPPRESS, &scan_suppress, sizeof(int), true); +- if (unlikely(err)) { +- WL_ERR(("Scan Supress Setting failed(%d)\n", err)); +- return err; +- } +- } +- +- join_params.params.chanspec_list[0] = chanspec; +- join_params.params.chanspec_num = 1; +- wldev_iovar_setint(dev, "chanspec", chanspec); +- join_params_size = sizeof(join_params); +- +- /* Disable Authentication, IBSS will add key if it required */ +- wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_DISABLED); +- wldev_iovar_setint(dev, "wsec", 0); +- + err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, +- join_params_size, true); ++ sizeof(join_params), true); + if (unlikely(err)) { + WL_ERR(("Error (%d)\n", err)); + return err; + } +- +- if (IBSS_INITIAL_SCAN_ALLOWED == FALSE) { +- scan_suppress = FALSE; +- /* Restore the SCAN SUPPRESS Falg */ +- err = wldev_ioctl(dev, WLC_SET_SCANSUPPRESS, +- &scan_suppress, sizeof(int), true); +- if (unlikely(err)) { +- WL_ERR(("Reset SCAN Suppress Flag failed (%d)\n", err)); +- return err; +- } +- } +- wl_update_prof(wl, dev, NULL, &join_params.ssid, WL_PROF_SSID); + return err; + } + +@@ -2796,31 +2418,13 @@ static s32 wl_cfg80211_leave_ibss(struct + { + struct wl_priv *wl = wiphy_priv(wiphy); + s32 err = 0; +- scb_val_t scbval; +- u8 *curbssid; + +- RETURN_EIO_IF_NOT_UP(wl); ++ CHECK_SYS_UP(wl); + wl_link_down(wl); +- WL_ERR(("Leave IBSS\n")); +- curbssid = wl_read_prof(wl, dev, WL_PROF_BSSID); +- wl_set_drv_status(wl, DISCONNECTING, dev); +- scbval.val = 0; +- memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN); +- err = wldev_ioctl(dev, WLC_DISASSOC, &scbval, +- sizeof(scb_val_t), true); +- if (unlikely(err)) { +- wl_clr_drv_status(wl, DISCONNECTING, dev); +- WL_ERR(("error(%d)\n", err)); +- return err; +- } +- +- /* remove the VSIE */ +- wl_cfg80211_ibss_vsie_delete(dev); + + return err; + } + +- + static s32 + wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme) + { +@@ -2828,11 +2432,7 @@ wl_set_wpa_version(struct net_device *de + struct wl_security *sec; + s32 val = 0; + s32 err = 0; +- s32 bssidx; +- if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { +- WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); +- return BCME_ERROR; +- } ++ s32 bssidx = wl_cfgp2p_find_idx(wl, dev); + + if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) + val = WPA_AUTH_PSK | +@@ -2846,6 +2446,13 @@ wl_set_wpa_version(struct net_device *de + if (is_wps_conn(sme)) + val = WPA_AUTH_DISABLED; + ++#ifdef BCMWAPI_WPI ++ if (sme->crypto.wpa_versions & NL80211_WAPI_VERSION_1) { ++ WL_DBG((" * wl_set_wpa_version, set wpa_auth" ++ " to WPA_AUTH_WAPI 0x400")); ++ val = WAPI_AUTH_PSK; /* | WAPI_AUTH_UNSPECIFIED; */ ++ } ++#endif + WL_DBG(("setting wpa_auth to 0x%0x\n", val)); + err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx); + if (unlikely(err)) { +@@ -2857,6 +2464,28 @@ wl_set_wpa_version(struct net_device *de + return err; + } + ++#ifdef BCMWAPI_WPI ++static s32 ++wl_set_set_wapi_ie(struct net_device *dev, struct cfg80211_connect_params *sme) ++{ ++ struct wl_priv *wl = wlcfg_drv_priv; ++ s32 err = 0; ++ s32 bssidx = wl_cfgp2p_find_idx(wl, dev); ++ ++ WL_DBG((" %s \n", __FUNCTION__)); ++ ++ if (sme->crypto.wpa_versions & NL80211_WAPI_VERSION_1) { ++ err = wldev_iovar_setbuf_bsscfg(dev, "wapiie", sme->ie, ++ sme->ie_len, wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync); ++ if (unlikely(err)) { ++ WL_ERR(("===> set_wapi_ie Error (%d)\n", err)); ++ return err; ++ } ++ } else ++ WL_DBG((" * skip \n")); ++ return err; ++} ++#endif /* BCMWAPI_WPI */ + + static s32 + wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme) +@@ -2865,12 +2494,7 @@ wl_set_auth_type(struct net_device *dev, + struct wl_security *sec; + s32 val = 0; + s32 err = 0; +- s32 bssidx; +- if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { +- WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); +- return BCME_ERROR; +- } +- ++ s32 bssidx = wl_cfgp2p_find_idx(wl, dev); + switch (sme->auth_type) { + case NL80211_AUTHTYPE_OPEN_SYSTEM: + val = WL_AUTH_OPEN_SYSTEM; +@@ -2908,13 +2532,10 @@ wl_set_set_cipher(struct net_device *dev + s32 pval = 0; + s32 gval = 0; + s32 err = 0; +- s32 wsec_val = 0; +- +- s32 bssidx; +- if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { +- WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); +- return BCME_ERROR; +- } ++#ifdef BCMWAPI_WPI ++ s32 val = 0; ++#endif ++ s32 bssidx = wl_cfgp2p_find_idx(wl, dev); + + if (sme->crypto.n_ciphers_pairwise) { + switch (sme->crypto.ciphers_pairwise[0]) { +@@ -2926,9 +2547,17 @@ wl_set_set_cipher(struct net_device *dev + pval = TKIP_ENABLED; + break; + case WLAN_CIPHER_SUITE_CCMP: ++ pval = AES_ENABLED; ++ break; + case WLAN_CIPHER_SUITE_AES_CMAC: + pval = AES_ENABLED; + break; ++#ifdef BCMWAPI_WPI ++ case WLAN_CIPHER_SUITE_SMS4: ++ val = SMS4_ENABLED; ++ pval = SMS4_ENABLED; ++ break; ++#endif + default: + WL_ERR(("invalid cipher pairwise (%d)\n", + sme->crypto.ciphers_pairwise[0])); +@@ -2950,6 +2579,12 @@ wl_set_set_cipher(struct net_device *dev + case WLAN_CIPHER_SUITE_AES_CMAC: + gval = AES_ENABLED; + break; ++#ifdef BCMWAPI_WPI ++ case WLAN_CIPHER_SUITE_SMS4: ++ val = SMS4_ENABLED; ++ gval = SMS4_ENABLED; ++ break; ++#endif + default: + WL_ERR(("invalid cipher group (%d)\n", + sme->crypto.cipher_group)); +@@ -2962,16 +2597,19 @@ wl_set_set_cipher(struct net_device *dev + if (is_wps_conn(sme)) { + if (sme->privacy) + err = wldev_iovar_setint_bsscfg(dev, "wsec", 4, bssidx); ++#ifdef BCMWAPI_WPI ++ else if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_SMS4) { ++ WL_DBG((" NO, is_wps_conn, WAPI set to SMS4_ENABLED")); ++ err = wldev_iovar_setint_bsscfg(dev, "wsec", val, bssidx); ++ } ++#endif + else + /* WPS-2.0 allows no security */ + err = wldev_iovar_setint_bsscfg(dev, "wsec", 0, bssidx); + } else { + WL_DBG((" NO, is_wps_conn, Set pval | gval to WSEC")); +- wsec_val = pval | gval; +- +- WL_DBG((" Set WSEC to fW 0x%x \n", wsec_val)); + err = wldev_iovar_setint_bsscfg(dev, "wsec", +- wsec_val, bssidx); ++ pval | gval, bssidx); + } + if (unlikely(err)) { + WL_ERR(("error (%d)\n", err)); +@@ -2992,11 +2630,7 @@ wl_set_key_mgmt(struct net_device *dev, + struct wl_security *sec; + s32 val = 0; + s32 err = 0; +- s32 bssidx; +- if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { +- WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); +- return BCME_ERROR; +- } ++ s32 bssidx = wl_cfgp2p_find_idx(wl, dev); + + if (sme->crypto.n_akm_suites) { + err = wldev_iovar_getint(dev, "wpa_auth", &val); +@@ -3033,9 +2667,24 @@ wl_set_key_mgmt(struct net_device *dev, + return -EINVAL; + } + } ++#ifdef BCMWAPI_WPI ++ else if (val & (WAPI_AUTH_PSK | WAPI_AUTH_UNSPECIFIED)) { ++ switch (sme->crypto.akm_suites[0]) { ++ case WLAN_AKM_SUITE_WAPI_CERT: ++ val = WAPI_AUTH_UNSPECIFIED; ++ break; ++ case WLAN_AKM_SUITE_WAPI_PSK: ++ val = WAPI_AUTH_PSK; ++ break; ++ default: ++ WL_ERR(("invalid cipher group (%d)\n", ++ sme->crypto.cipher_group)); ++ return -EINVAL; ++ } ++ } ++#endif + WL_DBG(("setting wpa_auth to %d\n", val)); + +- + err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx); + if (unlikely(err)) { + WL_ERR(("could not set wpa_auth (%d)\n", err)); +@@ -3057,11 +2706,7 @@ wl_set_set_sharedkey(struct net_device * + struct wl_wsec_key key; + s32 val; + s32 err = 0; +- s32 bssidx; +- if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { +- WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); +- return BCME_ERROR; +- } ++ s32 bssidx = wl_cfgp2p_find_idx(wl, dev); + + WL_DBG(("key len (%d)\n", sme->key_len)); + if (sme->key_len) { +@@ -3069,9 +2714,17 @@ wl_set_set_sharedkey(struct net_device * + WL_DBG(("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)) && ++ NL80211_WPA_VERSION_2 ++#ifdef BCMWAPI_WPI ++ | NL80211_WAPI_VERSION_1 ++#endif ++ )) && + (sec->cipher_pairwise & (WLAN_CIPHER_SUITE_WEP40 | +- WLAN_CIPHER_SUITE_WEP104))) ++ WLAN_CIPHER_SUITE_WEP104 ++#ifdef BCMWAPI_WPI ++ | WLAN_CIPHER_SUITE_SMS4 ++#endif ++ ))) + { + memset(&key, 0, sizeof(key)); + key.len = (u32) sme->key_len; +@@ -3089,6 +2742,11 @@ wl_set_set_sharedkey(struct net_device * + case WLAN_CIPHER_SUITE_WEP104: + key.algo = CRYPTO_ALGO_WEP128; + break; ++#ifdef BCMWAPI_WPI ++ case WLAN_CIPHER_SUITE_SMS4: ++ key.algo = CRYPTO_ALGO_SMS4; ++ break; ++#endif + default: + WL_ERR(("Invalid algorithm (%d)\n", + sme->crypto.ciphers_pairwise[0])); +@@ -3119,11 +2777,10 @@ wl_set_set_sharedkey(struct net_device * + return err; + } + +-#if defined(ESCAN_RESULT_PATCH) ++#ifdef ESCAN_RESULT_PATCH + static u8 connect_req_bssid[6]; + static u8 broad_bssid[6]; +-#endif /* ESCAN_RESULT_PATCH */ +- ++#endif + + + static s32 +@@ -3135,9 +2792,6 @@ wl_cfg80211_connect(struct wiphy *wiphy, + wl_extjoin_params_t *ext_join_params; + struct wl_join_params join_params; + size_t join_params_size; +-#if defined(ROAM_ENABLE) && defined(ROAM_AP_ENV_DETECTION) +- dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); +-#endif /* ROAM_AP_ENV_DETECTION */ + s32 err = 0; + wpa_ie_fixed_t *wpa_ie; + bcm_tlv_t *wpa2_ie; +@@ -3145,9 +2799,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, + u32 wpaie_len = 0; + u32 chan_cnt = 0; + struct ether_addr bssid; +- s32 bssidx; + int ret; +- int wait_cnt; + + WL_DBG(("In\n")); + +@@ -3156,13 +2808,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, + return -EOPNOTSUPP; + } + +- if (unlikely(sme->ssid_len > DOT11_MAX_SSID_LEN)) { +- WL_ERR(("Invalid SSID info: SSID=%s, length=%d\n", +- sme->ssid, sme->ssid_len)); +- return -EINVAL; +- } +- +- RETURN_EIO_IF_NOT_UP(wl); ++ CHECK_SYS_UP(wl); + + /* + * Cancel ongoing scan to sync up with sme state machine of cfg80211. +@@ -3172,21 +2818,16 @@ wl_cfg80211_connect(struct wiphy *wiphy, + wl_notify_escan_complete(wl, dev, true, true); + } + #endif +-#ifdef WL_SCHED_SCAN +- if (wl->sched_scan_req) { +- wl_cfg80211_sched_scan_stop(wiphy, wl_to_prmry_ndev(wl)); +- } +-#endif +-#if defined(ESCAN_RESULT_PATCH) +- if (sme->bssid) ++#ifdef ESCAN_RESULT_PATCH ++ if (sme->bssid) { + memcpy(connect_req_bssid, sme->bssid, ETHER_ADDR_LEN); +- else ++ } ++ else { + bzero(connect_req_bssid, ETHER_ADDR_LEN); ++ } + bzero(broad_bssid, ETHER_ADDR_LEN); + #endif +-#if defined(USE_DYNAMIC_MAXPKT_RXGLOM) +- maxrxpktglom = 0; +-#endif ++ + bzero(&bssid, sizeof(bssid)); + if (!wl_get_drv_status(wl, CONNECTED, dev)&& + (ret = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false)) == 0) { +@@ -3206,23 +2847,12 @@ wl_cfg80211_connect(struct wiphy *wiphy, + WL_ERR(("error (%d)\n", err)); + return err; + } +- wait_cnt = 500/10; +- while (wl_get_drv_status(wl, DISCONNECTING, dev) && wait_cnt) { +- WL_DBG(("Waiting for disconnection terminated, wait_cnt: %d\n", +- wait_cnt)); +- wait_cnt--; +- OSL_SLEEP(10); ++ while (wl_get_drv_status(wl, DISCONNECTING, dev)) { ++ WL_ERR(("Waiting for disconnection terminated.\n")); ++ msleep(20); + } + } else + WL_DBG(("Currently not associated!\n")); +- } else { +- /* if status is DISCONNECTING, wait for disconnection terminated max 500 ms */ +- wait_cnt = 500/10; +- while (wl_get_drv_status(wl, DISCONNECTING, dev) && wait_cnt) { +- WL_DBG(("Waiting for disconnection terminated, wait_cnt: %d\n", wait_cnt)); +- wait_cnt--; +- OSL_SLEEP(10); +- } + } + + /* Clean BSSID */ +@@ -3232,11 +2862,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, + + if (p2p_is_on(wl) && (dev != wl_to_prmry_ndev(wl))) { + /* we only allow to connect using virtual interface in case of P2P */ +- if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { +- WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); +- return BCME_ERROR; +- } +- wl_cfgp2p_set_management_ie(wl, dev, bssidx, ++ wl_cfgp2p_set_management_ie(wl, dev, wl_cfgp2p_find_idx(wl, dev), + VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len); + } else if (dev == wl_to_prmry_ndev(wl)) { + /* find the RSN_IE */ +@@ -3260,27 +2886,13 @@ wl_cfg80211_connect(struct wiphy *wiphy, + wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync); + } + +- if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { +- WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); +- return BCME_ERROR; +- } +- err = wl_cfgp2p_set_management_ie(wl, dev, bssidx, ++ err = wl_cfgp2p_set_management_ie(wl, dev, wl_cfgp2p_find_idx(wl, dev), + VNDR_IE_ASSOCREQ_FLAG, (u8 *)sme->ie, sme->ie_len); + if (unlikely(err)) { + return err; + } + } +-#if defined(ROAM_ENABLE) && defined(ROAM_AP_ENV_DETECTION) +- if (dhd->roam_env_detection && (wldev_iovar_setint(dev, "roam_env_detection", +- AP_ENV_DETECT_NOT_USED) == BCME_OK)) { +- s32 roam_trigger[2] = {WL_AUTO_ROAM_TRIGGER, WLC_BAND_ALL}; +- err = wldev_ioctl(dev, WLC_SET_ROAM_TRIGGER, roam_trigger, +- sizeof(roam_trigger), true); +- if (unlikely(err)) { +- WL_ERR((" failed to restore roam_trigger for auto env detection\n")); +- } +- } +-#endif /* ROAM_AP_ENV_DETECTION */ ++ + if (chan) { + wl->channel = ieee80211_frequency_to_channel(chan->center_freq); + chan_cnt = 1; +@@ -3288,6 +2900,17 @@ wl_cfg80211_connect(struct wiphy *wiphy, + chan->center_freq, chan_cnt)); + } else + wl->channel = 0; ++ ++#ifdef BCMWAPI_WPI ++ WL_DBG(("1. enable wapi auth\n")); ++ if (sme->crypto.wpa_versions & NL80211_WAPI_VERSION_1) { ++ WL_DBG(("2. set wapi ie \n")); ++ err = wl_set_set_wapi_ie(dev, sme); ++ if (unlikely(err)) ++ return err; ++ } else ++ WL_DBG(("2. Not wapi ie \n")); ++#endif + WL_DBG(("ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len)); + WL_DBG(("3. set wapi version \n")); + err = wl_set_wpa_version(dev, sme); +@@ -3295,11 +2918,21 @@ wl_cfg80211_connect(struct wiphy *wiphy, + WL_ERR(("Invalid wpa_version\n")); + return err; + } ++#ifdef BCMWAPI_WPI ++ if (sme->crypto.wpa_versions & NL80211_WAPI_VERSION_1) ++ WL_DBG(("4. WAPI Dont Set wl_set_auth_type\n")); ++ else { ++ WL_DBG(("4. wl_set_auth_type\n")); ++#endif + err = wl_set_auth_type(dev, sme); + if (unlikely(err)) { + WL_ERR(("Invalid auth type\n")); + return err; + } ++#ifdef BCMWAPI_WPI ++ ++ } ++#endif + + err = wl_set_set_cipher(dev, sme); + if (unlikely(err)) { +@@ -3336,14 +2969,14 @@ wl_cfg80211_connect(struct wiphy *wiphy, + wl_update_prof(wl, dev, NULL, &ext_join_params->ssid, WL_PROF_SSID); + ext_join_params->ssid.SSID_len = htod32(ext_join_params->ssid.SSID_len); + /* increate dwell time to receive probe response or detect Beacon +- * from target AP at a noisy air only when channel info is provided in connect command ++ * from target AP at a noisy air only during connect command + */ +- ext_join_params->scan.active_time = chan_cnt ? WL_SCAN_JOIN_ACTIVE_DWELL_TIME_MS : -1; +- ext_join_params->scan.passive_time = chan_cnt ? WL_SCAN_JOIN_PASSIVE_DWELL_TIME_MS : -1; ++ ext_join_params->scan.active_time = WL_SCAN_JOIN_ACTIVE_DWELL_TIME_MS; ++ ext_join_params->scan.passive_time = WL_SCAN_JOIN_PASSIVE_DWELL_TIME_MS; + /* Set up join scan parameters */ + ext_join_params->scan.scan_type = -1; +- ext_join_params->scan.nprobes = chan_cnt ? +- (ext_join_params->scan.active_time/WL_SCAN_JOIN_PROBE_INTERVAL_MS) : -1; ++ ext_join_params->scan.nprobes ++ = (ext_join_params->scan.active_time/WL_SCAN_JOIN_PROBE_INTERVAL_MS); + ext_join_params->scan.home_time = -1; + + if (sme->bssid) +@@ -3371,13 +3004,8 @@ wl_cfg80211_connect(struct wiphy *wiphy, + ext_join_params->ssid.SSID_len)); + } + wl_set_drv_status(wl, CONNECTING, dev); +- +- if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { +- WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); +- return BCME_ERROR; +- } + err = wldev_iovar_setbuf_bsscfg(dev, "join", ext_join_params, join_params_size, +- wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync); ++ wl->ioctl_buf, WLC_IOCTL_MAXLEN, wl_cfgp2p_find_idx(wl, dev), &wl->ioctl_buf_sync); + kfree(ext_join_params); + if (err) { + wl_clr_drv_status(wl, CONNECTING, dev); +@@ -3403,7 +3031,7 @@ set_ssid: + memcpy(&join_params.params.bssid, ðer_bcast, ETH_ALEN); + + wl_ch_to_chanspec(wl->channel, &join_params, &join_params_size); +- WL_DBG(("join_param_size %zu\n", join_params_size)); ++ WL_DBG(("join_param_size %d\n", join_params_size)); + + if (join_params.ssid.SSID_len < IEEE80211_MAX_SSID_LEN) { + WL_INFO(("ssid \"%s\", len (%d)\n", join_params.ssid.SSID, +@@ -3429,7 +3057,7 @@ wl_cfg80211_disconnect(struct wiphy *wip + s32 err = 0; + u8 *curbssid; + WL_ERR(("Reason %d\n", reason_code)); +- RETURN_EIO_IF_NOT_UP(wl); ++ CHECK_SYS_UP(wl); + act = *(bool *) wl_read_prof(wl, dev, WL_PROF_ACT); + curbssid = wl_read_prof(wl, dev, WL_PROF_BSSID); + if (act) { +@@ -3458,15 +3086,9 @@ wl_cfg80211_disconnect(struct wiphy *wip + return err; + } + +-#if defined(WL_CFG80211_P2P_DEV_IF) +-static s32 +-wl_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, +- enum nl80211_tx_power_setting type, s32 mbm) +-#else + static s32 + wl_cfg80211_set_tx_power(struct wiphy *wiphy, + enum nl80211_tx_power_setting type, s32 dbm) +-#endif /* WL_CFG80211_P2P_DEV_IF */ + { + + struct wl_priv *wl = wiphy_priv(wiphy); +@@ -3474,14 +3096,8 @@ wl_cfg80211_set_tx_power(struct wiphy *w + u16 txpwrmw; + s32 err = 0; + s32 disable = 0; +- s32 txpwrqdbm; +-#if defined(WL_CFG80211_P2P_DEV_IF) +- s32 dbm = MBM_TO_DBM(mbm); +-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) +- dbm = MBM_TO_DBM(dbm); +-#endif /* WL_CFG80211_P2P_DEV_IF */ + +- RETURN_EIO_IF_NOT_UP(wl); ++ CHECK_SYS_UP(wl); + switch (type) { + case NL80211_TX_POWER_AUTOMATIC: + break; +@@ -3511,14 +3127,8 @@ wl_cfg80211_set_tx_power(struct wiphy *w + txpwrmw = 0xffff; + else + txpwrmw = (u16) dbm; +- txpwrqdbm = (s32)bcm_mw_to_qdbm(txpwrmw); +-#ifdef SUPPORT_WL_TXPOWER +- if (type == NL80211_TX_POWER_AUTOMATIC) +- txpwrqdbm = 127; +- else +- txpwrqdbm |= WL_TXPWR_OVERRIDE; +-#endif /* SUPPORT_WL_TXPOWER */ +- err = wldev_iovar_setint(ndev, "qtxpower", txpwrqdbm); ++ err = wldev_iovar_setint(ndev, "qtxpower", ++ (s32) (bcm_mw_to_qdbm(txpwrmw))); + if (unlikely(err)) { + WL_ERR(("qtxpower error (%d)\n", err)); + return err; +@@ -3528,12 +3138,7 @@ wl_cfg80211_set_tx_power(struct wiphy *w + return err; + } + +-#if defined(WL_CFG80211_P2P_DEV_IF) +-static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, +- struct wireless_dev *wdev, s32 *dbm) +-#else + static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm) +-#endif /* WL_CFG80211_P2P_DEV_IF */ + { + struct wl_priv *wl = wiphy_priv(wiphy); + struct net_device *ndev = wl_to_prmry_ndev(wl); +@@ -3541,7 +3146,7 @@ static s32 wl_cfg80211_get_tx_power(stru + u8 result; + s32 err = 0; + +- RETURN_EIO_IF_NOT_UP(wl); ++ CHECK_SYS_UP(wl); + err = wldev_iovar_getint(ndev, "qtxpower", &txpwrdbm); + if (unlikely(err)) { + WL_ERR(("error (%d)\n", err)); +@@ -3561,21 +3166,16 @@ wl_cfg80211_config_default_key(struct wi + u32 index; + s32 wsec; + s32 err = 0; +- s32 bssidx; +- if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { +- WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); +- return BCME_ERROR; +- } ++ s32 bssidx = wl_cfgp2p_find_idx(wl, dev); + + WL_DBG(("key index (%d)\n", key_idx)); +- RETURN_EIO_IF_NOT_UP(wl); ++ CHECK_SYS_UP(wl); + err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx); + if (unlikely(err)) { + WL_ERR(("WLC_GET_WSEC error (%d)\n", err)); + return err; + } +- /* fix IOT issue with Apple Airport */ +- if (wsec == WEP_ENABLED) { ++ if (wsec & WEP_ENABLED) { + /* Just select a new current key */ + index = (u32) key_idx; + index = htod32(index); +@@ -3595,12 +3195,8 @@ wl_add_keyext(struct wiphy *wiphy, struc + struct wl_priv *wl = wiphy_priv(wiphy); + struct wl_wsec_key key; + s32 err = 0; +- s32 bssidx; ++ s32 bssidx = wl_cfgp2p_find_idx(wl, dev); + s32 mode = wl_get_mode_by_netdev(wl, dev); +- if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { +- WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); +- return BCME_ERROR; +- } + memset(&key, 0, sizeof(key)); + key.index = (u32) key_idx; + +@@ -3666,6 +3262,12 @@ wl_add_keyext(struct wiphy *wiphy, struc + key.algo = CRYPTO_ALGO_AES_CCM; + WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n")); + break; ++#ifdef BCMWAPI_WPI ++ case WLAN_CIPHER_SUITE_SMS4: ++ key.algo = CRYPTO_ALGO_SMS4; ++ WL_DBG(("WLAN_CIPHER_SUITE_SMS4\n")); ++ break; ++#endif + default: + WL_ERR(("Invalid cipher (0x%x)\n", params->cipher)); + return -EINVAL; +@@ -3697,18 +3299,13 @@ wl_cfg80211_add_key(struct wiphy *wiphy, + struct wl_priv *wl = wiphy_priv(wiphy); + s32 mode = wl_get_mode_by_netdev(wl, dev); + WL_DBG(("key index (%d)\n", key_idx)); +- RETURN_EIO_IF_NOT_UP(wl); ++ CHECK_SYS_UP(wl); + +- if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { +- WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); +- return BCME_ERROR; +- } ++ bssidx = wl_cfgp2p_find_idx(wl, dev); + +- if (mac_addr && +- ((params->cipher != WLAN_CIPHER_SUITE_WEP40) && +- (params->cipher != WLAN_CIPHER_SUITE_WEP104))) { +- wl_add_keyext(wiphy, dev, key_idx, mac_addr, params); +- goto exit; ++ if (mac_addr) { ++ wl_add_keyext(wiphy, dev, key_idx, mac_addr, params); ++ goto exit; + } + memset(&key, 0, sizeof(key)); + +@@ -3754,16 +3351,20 @@ wl_cfg80211_add_key(struct wiphy *wiphy, + val = AES_ENABLED; + WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n")); + break; ++#ifdef BCMWAPI_WPI ++ case WLAN_CIPHER_SUITE_SMS4: ++ key.algo = CRYPTO_ALGO_SMS4; ++ val = SMS4_ENABLED; ++ WL_DBG((" * wl_cfg80211_add_key, set key " ++ " to WLAN_CIPHER_SUITE_SMS4\n")); ++ break; ++#endif /* BCMWAPI_WPI */ + default: + WL_ERR(("Invalid cipher (0x%x)\n", params->cipher)); + return -EINVAL; + } + + /* Set the new key/index */ +- if ((mode == WL_MODE_IBSS) && (val & (TKIP_ENABLED | AES_ENABLED))) { +- WL_ERR(("IBSS KEY setted\n")); +- wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_NONE); +- } + swap_key_from_BE(&key); + err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), wl->ioctl_buf, + WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync); +@@ -3796,19 +3397,14 @@ wl_cfg80211_del_key(struct wiphy *wiphy, + struct wl_wsec_key key; + struct wl_priv *wl = wiphy_priv(wiphy); + s32 err = 0; +- s32 bssidx; +- if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { +- WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); +- return BCME_ERROR; +- } +- WL_DBG(("Enter\n")); ++ s32 bssidx = wl_cfgp2p_find_idx(wl, dev); + ++ WL_DBG(("Enter\n")); + #ifndef IEEE80211W + if ((key_idx >= DOT11_MAX_DEFAULT_KEYS) && (key_idx < DOT11_MAX_DEFAULT_KEYS+2)) + return -EINVAL; + #endif +- +- RETURN_EIO_IF_NOT_UP(wl); ++ CHECK_SYS_UP(wl); + memset(&key, 0, sizeof(key)); + + key.flags = WL_PRIMARY_KEY; +@@ -3845,13 +3441,10 @@ wl_cfg80211_get_key(struct wiphy *wiphy, + struct wl_security *sec; + s32 wsec; + s32 err = 0; +- s32 bssidx; +- if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { +- WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); +- return BCME_ERROR; +- } ++ s32 bssidx = wl_cfgp2p_find_idx(wl, dev); ++ + WL_DBG(("key index (%d)\n", key_idx)); +- RETURN_EIO_IF_NOT_UP(wl); ++ CHECK_SYS_UP(wl); + memset(&key, 0, sizeof(key)); + key.index = key_idx; + swap_key_to_BE(&key); +@@ -3859,7 +3452,7 @@ wl_cfg80211_get_key(struct wiphy *wiphy, + params.key_len = (u8) min_t(u8, DOT11_MAX_KEY_SIZE, key.len); + memcpy(params.key, key.data, params.key_len); + +- err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx); ++ wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx); + if (unlikely(err)) { + WL_ERR(("WLC_GET_WSEC error (%d)\n", err)); + return err; +@@ -3883,6 +3476,13 @@ wl_cfg80211_get_key(struct wiphy *wiphy, + params.cipher = WLAN_CIPHER_SUITE_AES_CMAC; + WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n")); + break; ++#ifdef BCMWAPI_WPI ++ case WLAN_CIPHER_SUITE_SMS4: ++ key.algo = CRYPTO_ALGO_SMS4; ++ WL_DBG((" * wl_cfg80211_add_key, set key" ++ "to WLAN_CIPHER_SUITE_SMS4\n")); ++ break; ++#endif + default: + WL_ERR(("Invalid algo (0x%x)\n", wsec)); + return -EINVAL; +@@ -3914,7 +3514,7 @@ wl_cfg80211_get_station(struct wiphy *wi + s8 eabuf[ETHER_ADDR_STR_LEN]; + #endif + dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); +- RETURN_EIO_IF_NOT_UP(wl); ++ CHECK_SYS_UP(wl); + if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_AP) { + err = wldev_iovar_getbuf(dev, "sta_info", (struct ether_addr *)mac, + ETHER_ADDR_LEN, wl->ioctl_buf, WLC_IOCTL_SMLEN, &wl->ioctl_buf_sync); +@@ -3939,8 +3539,7 @@ wl_cfg80211_get_station(struct wiphy *wi + bcm_ether_ntoa((const struct ether_addr *)mac, eabuf), sinfo->inactive_time, + sta->idle * 1000)); + #endif +- } else if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_BSS || +- wl_get_mode_by_netdev(wl, dev) == WL_MODE_IBSS) { ++ } else if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_BSS) { + get_pktcnt_t pktcnt; + u8 *curmacp = wl_read_prof(wl, dev, WL_PROF_BSSID); + if (!wl_get_drv_status(wl, CONNECTED, dev) || +@@ -3961,28 +3560,10 @@ wl_cfg80211_get_station(struct wiphy *wi + if (err) { + WL_ERR(("Could not get rate (%d)\n", err)); + } else { +-#if defined(USE_DYNAMIC_MAXPKT_RXGLOM) +- int rxpktglom; +-#endif + rate = dtoh32(rate); + sinfo->filled |= STATION_INFO_TX_BITRATE; + sinfo->txrate.legacy = rate * 5; + WL_DBG(("Rate %d Mbps\n", (rate / 2))); +-#if defined(USE_DYNAMIC_MAXPKT_RXGLOM) +- rxpktglom = ((rate/2) > 150) ? 20 : 10; +- +- if (maxrxpktglom != rxpktglom) { +- maxrxpktglom = rxpktglom; +- WL_DBG(("Rate %d Mbps, update bus:maxtxpktglom=%d\n", (rate/2), +- maxrxpktglom)); +- err = wldev_iovar_setbuf(dev, "bus:maxtxpktglom", +- (char*)&maxrxpktglom, 4, wl->ioctl_buf, +- WLC_IOCTL_MAXLEN, NULL); +- if (err < 0) { +- WL_ERR(("set bus:maxtxpktglom failed, %d\n", err)); +- } +- } +-#endif + } + + memset(&scb_val, 0, sizeof(scb_val)); +@@ -3993,7 +3574,10 @@ wl_cfg80211_get_station(struct wiphy *wi + WL_ERR(("Could not get rssi (%d)\n", err)); + goto get_station_err; + } +- rssi = dtoh32(scb_val.val) + RSSI_OFFSET; ++ rssi = dtoh32(scb_val.val); ++#if defined(RSSIOFFSET) ++ rssi = wl_update_rssi_offset(rssi); ++#endif + sinfo->filled |= STATION_INFO_SIGNAL; + sinfo->signal = rssi; + WL_DBG(("RSSI %d dBm\n", rssi)); +@@ -4012,15 +3596,12 @@ wl_cfg80211_get_station(struct wiphy *wi + get_station_err: + if (err && (err != -ERESTARTSYS)) { + /* Disconnect due to zero BSSID or error to get RSSI */ +- WL_ERR(("force cfg80211_disconnected: %d\n", err)); ++ WL_ERR(("force cfg80211_disconnected\n")); + wl_clr_drv_status(wl, CONNECTED, dev); + cfg80211_disconnected(dev, 0, NULL, 0, GFP_KERNEL); + wl_link_down(wl); + } + } +- else { +- WL_ERR(("Invalid device mode %d\n", wl_get_mode_by_netdev(wl, dev))); +- } + + return err; + } +@@ -4053,35 +3634,25 @@ wl_cfg80211_set_power_mgmt(struct wiphy + struct net_info *_net_info = wl_get_netinfo_by_netdev(wl, dev); + #if !defined(SUPPORT_PM2_ONLY) + dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); +-#endif +- RETURN_EIO_IF_NOT_UP(wl); +- WL_DBG(("Enter\n")); +-#if defined(WL_ENABLE_P2P_IF) +- if (wl->p2p_net == dev || _net_info == NULL || wl->vsdb_mode || +- !wl_get_drv_status(wl, CONNECTED, dev)) { +-#else +- if (_net_info == NULL || wl->vsdb_mode || +- !wl_get_drv_status(wl, CONNECTED, dev)) { +-#endif /* WL_ENABLE_P2P_IF */ ++#endif /* (OEM_ANDROID) */ ++ CHECK_SYS_UP(wl); ++ ++ if (wl->p2p_net == dev || _net_info == NULL) { + return err; + } + WL_DBG(("%s: Enter power save enabled %d\n", dev->name, enabled)); + +- /* Delete pm_enable_work */ +- if (wl->pm_enable_work_on) { +- cancel_delayed_work_sync(&wl->pm_enable_work); +- wl->pm_enable_work_on = false; +- } +- + #if !defined(SUPPORT_PM2_ONLY) + /* android has special hooks to change pm when kernel suspended */ + pm = enabled ? ((dhd->in_suspend) ? PM_MAX : PM_FAST) : PM_OFF; + #else + pm = enabled ? PM_FAST : PM_OFF; + #endif /* SUPPORT_PM2_ONLY */ +- if (_net_info->pm_block) { +- WL_ERR(("%s:Do not enable the power save for pm_block %d\n", +- dev->name, _net_info->pm_block)); ++ ++ if (_net_info->pm_block || wl->vsdb_mode) { ++ /* Do not enable the power save if it is p2p interface or vsdb mode is set */ ++ WL_DBG(("%s:Do not enable the power save for pm_block %d or vsdb_mode %d\n", ++ dev->name, _net_info->pm_block, wl->vsdb_mode)); + pm = PM_OFF; + } + pm = htod32(pm); +@@ -4140,10 +3711,11 @@ static s32 wl_cfg80211_resume(struct wip + return err; + } + ++static s32 + #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39) +-static s32 wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow) ++wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow) + #else +-static s32 wl_cfg80211_suspend(struct wiphy *wiphy) ++wl_cfg80211_suspend(struct wiphy *wiphy) + #endif + { + #ifdef DHD_CLEAR_ON_SUSPEND +@@ -4223,7 +3795,7 @@ wl_cfg80211_set_pmksa(struct wiphy *wiph + s32 err = 0; + int i; + +- RETURN_EIO_IF_NOT_UP(wl); ++ CHECK_SYS_UP(wl); + for (i = 0; i < wl->pmk_list->pmkids.npmkid; i++) + if (!memcmp(pmksa->bssid, &wl->pmk_list->pmkids.pmkid[i].BSSID, + ETHER_ADDR_LEN)) +@@ -4256,11 +3828,11 @@ wl_cfg80211_del_pmksa(struct wiphy *wiph + struct cfg80211_pmksa *pmksa) + { + struct wl_priv *wl = wiphy_priv(wiphy); +- struct _pmkid_list pmkid = {0}; ++ struct _pmkid_list pmkid; + s32 err = 0; + int i; + +- RETURN_EIO_IF_NOT_UP(wl); ++ CHECK_SYS_UP(wl); + memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETHER_ADDR_LEN); + memcpy(pmkid.pmkid[0].PMKID, pmksa->pmkid, WPA2_PMKID_LEN); + +@@ -4303,7 +3875,7 @@ wl_cfg80211_flush_pmksa(struct wiphy *wi + { + struct wl_priv *wl = wiphy_priv(wiphy); + s32 err = 0; +- RETURN_EIO_IF_NOT_UP(wl); ++ CHECK_SYS_UP(wl); + memset(wl->pmk_list, 0, sizeof(*wl->pmk_list)); + err = wl_update_pmklist(dev, wl->pmk_list, err); + return err; +@@ -4323,7 +3895,7 @@ wl_cfg80211_scan_alloc_params(int channe + params_size = WL_SCAN_PARAMS_FIXED_SIZE + 1 * sizeof(uint16); + params = (wl_scan_params_t*) kzalloc(params_size, GFP_KERNEL); + if (params == NULL) { +- WL_ERR(("mem alloc failed (%d bytes)\n", params_size)); ++ WL_ERR(("%s: mem alloc failed (%d bytes)\n", __func__, params_size)); + return params; + } + memset(params, 0, params_size); +@@ -4351,31 +3923,30 @@ wl_cfg80211_scan_alloc_params(int channe + return params; + } + +-#if defined(WL_CFG80211_P2P_DEV_IF) +-static s32 +-wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev, +- struct ieee80211_channel *channel, unsigned int duration, u64 *cookie) +-#else + static s32 +-wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev, ++wl_cfg80211_remain_on_channel(struct wiphy *wiphy, struct net_device *dev, + struct ieee80211_channel * channel, + enum nl80211_channel_type channel_type, + unsigned int duration, u64 *cookie) +-#endif /* WL_CFG80211_P2P_DEV_IF */ + { + s32 target_channel; + u32 id; +- s32 err = BCME_OK; + struct ether_addr primary_mac; + struct net_device *ndev = NULL; +- struct wl_priv *wl = wiphy_priv(wiphy); + +- ndev = cfgdev_to_wlc_ndev(cfgdev, wl); ++ s32 err = BCME_OK; ++ struct wl_priv *wl = wiphy_priv(wiphy); + +- WL_DBG(("Enter, channel: %d, duration ms (%d) SCANNING ?? %s \n", +- ieee80211_frequency_to_channel(channel->center_freq), ++ WL_DBG(("Enter, ifindex: %d, channel: %d, duration ms (%d) SCANNING ?? %s \n", ++ dev->ifindex, ieee80211_frequency_to_channel(channel->center_freq), + duration, (wl_get_drv_status(wl, SCANNING, ndev)) ? "YES":"NO")); + ++ if (wl->p2p_net == dev) { ++ ndev = wl_to_prmry_ndev(wl); ++ } else { ++ ndev = dev; ++ } ++ + if (!wl->p2p) { + WL_ERR(("wl->p2p is not initialized\n")); + err = BCME_ERROR; +@@ -4383,16 +3954,14 @@ wl_cfg80211_remain_on_channel(struct wip + } + + #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST +- if (wl_get_drv_status_all(wl, SCANNING)) { +- wl_notify_escan_complete(wl, wl->escan_info.ndev, true, true); ++ if (wl_get_drv_status(wl, SCANNING, ndev)) { ++ wl_notify_escan_complete(wl, ndev, true, true); + } + #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */ + + target_channel = ieee80211_frequency_to_channel(channel->center_freq); + memcpy(&wl->remain_on_chan, channel, sizeof(struct ieee80211_channel)); +-#if defined(WL_ENABLE_P2P_IF) + wl->remain_on_chan_type = channel_type; +-#endif /* WL_ENABLE_P2P_IF */ + id = ++wl->last_roc_id; + if (id == 0) + id = ++wl->last_roc_id; +@@ -4471,13 +4040,8 @@ wl_cfg80211_remain_on_channel(struct wip + exit: + if (err == BCME_OK) { + WL_INFO(("Success\n")); +-#if defined(WL_CFG80211_P2P_DEV_IF) +- cfg80211_ready_on_channel(cfgdev, *cookie, channel, +- duration, GFP_KERNEL); +-#else +- cfg80211_ready_on_channel(cfgdev, *cookie, channel, ++ cfg80211_ready_on_channel(dev, *cookie, channel, + channel_type, duration, GFP_KERNEL); +-#endif /* WL_CFG80211_P2P_DEV_IF */ + } else { + WL_ERR(("Fail to Set (err=%d cookie:%llu)\n", err, *cookie)); + } +@@ -4485,18 +4049,11 @@ exit: + } + + static s32 +-wl_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, +- bcm_struct_cfgdev *cfgdev, u64 cookie) ++wl_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, struct net_device *dev, ++ u64 cookie) + { + s32 err = 0; +- +-#if defined(WL_CFG80211_P2P_DEV_IF) +- if (cfgdev->iftype == NL80211_IFTYPE_P2P_DEVICE) { +- WL_DBG((" enter ) on P2P dedicated discover interface\n")); +- } +-#else +- WL_DBG((" enter ) netdev_ifidx: %d \n", cfgdev->ifindex)); +-#endif /* WL_CFG80211_P2P_DEV_IF */ ++ WL_DBG((" enter ) netdev_ifidx: %d \n", dev->ifindex)); + return err; + } + +@@ -4511,11 +4068,10 @@ wl_cfg80211_afx_handler(struct work_stru + if (afx_instance != NULL && wl->afx_hdl->is_active) { + if (wl->afx_hdl->is_listen && wl->afx_hdl->my_listen_chan) { + ret = wl_cfgp2p_discover_listen(wl, wl->afx_hdl->my_listen_chan, +- (100 * (1 + (RANDOM32() % 3)))); /* 100ms ~ 300ms */ ++ (100 * (1 + (random32() % 3)))); /* 100ms ~ 300ms */ + } else { + ret = wl_cfgp2p_act_frm_search(wl, wl->afx_hdl->dev, +- wl->afx_hdl->bssidx, wl->afx_hdl->peer_listen_chan, +- NULL); ++ wl->afx_hdl->bssidx, wl->afx_hdl->peer_listen_chan); + } + if (unlikely(ret != BCME_OK)) { + WL_ERR(("ERROR occurred! returned value is (%d)\n", ret)); +@@ -4550,7 +4106,7 @@ wl_cfg80211_af_searching_channel(struct + /* search peer on peer's listen channel */ + schedule_work(&wl->afx_hdl->work); + wait_for_completion_timeout(&wl->act_frm_scan, +- msecs_to_jiffies(WL_AF_SEARCH_TIME_MAX)); ++ msecs_to_jiffies(MAX_WAIT_TIME)); + + if ((wl->afx_hdl->peer_chan != WL_INVALID) || + !(wl_get_drv_status(wl, FINDING_COMMON_CHANNEL, dev))) +@@ -4563,12 +4119,10 @@ wl_cfg80211_af_searching_channel(struct + wl->afx_hdl->is_listen = TRUE; + schedule_work(&wl->afx_hdl->work); + wait_for_completion_timeout(&wl->act_frm_scan, +- msecs_to_jiffies(WL_AF_SEARCH_TIME_MAX)); ++ msecs_to_jiffies(MAX_WAIT_TIME)); + } +- if ((wl->afx_hdl->peer_chan != WL_INVALID) || +- !(wl_get_drv_status(wl, FINDING_COMMON_CHANNEL, dev))) ++ if (!wl_get_drv_status(wl, FINDING_COMMON_CHANNEL, dev)) + break; +- + wl->afx_hdl->retry++; + + WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(wl); +@@ -4611,7 +4165,6 @@ wl_cfg80211_config_p2p_pub_af_tx(struct + config_af_params->search_channel = false; + config_af_params->max_tx_retry = WL_AF_TX_MAX_RETRY; + config_af_params->mpc_onoff = -1; +- wl->next_af_subtype = P2P_PAF_SUBTYPE_INVALID; + + switch (act_frm->subtype) { + case P2P_PAF_GON_REQ: { +@@ -4630,7 +4183,7 @@ wl_cfg80211_config_p2p_pub_af_tx(struct + case P2P_PAF_GON_RSP: { + wl->next_af_subtype = act_frm->subtype + 1; + /* increase dwell time to wait for CONF frame */ +- af_params->dwell_time = WL_MED_DWELL_TIME + 100; ++ af_params->dwell_time = WL_MED_DWELL_TIME; + break; + } + case P2P_PAF_GON_CONF: { +@@ -4665,10 +4218,7 @@ wl_cfg80211_config_p2p_pub_af_tx(struct + #endif /* WL_CFG80211_SYNC_GON */ + break; + case P2P_PAF_DEVDIS_REQ: { +- if (IS_ACTPUB_WITHOUT_GROUP_ID(&act_frm->elts[0], +- action_frame->len)) { +- config_af_params->search_channel = true; +- } ++ config_af_params->search_channel = true; + + wl->next_af_subtype = act_frm->subtype + 1; + /* maximize dwell time to wait for RESP frame */ +@@ -4683,7 +4233,7 @@ wl_cfg80211_config_p2p_pub_af_tx(struct + #endif /* WL_CFG80211_SYNC_GON */ + break; + case P2P_PAF_PROVDIS_REQ: { +- if (IS_ACTPUB_WITHOUT_GROUP_ID(&act_frm->elts[0], ++ if (IS_PROV_DISC_WITHOUT_GROUP_ID(&act_frm->elts[0], + action_frame->len)) { + config_af_params->search_channel = true; + } +@@ -4696,7 +4246,8 @@ wl_cfg80211_config_p2p_pub_af_tx(struct + } + case P2P_PAF_PROVDIS_RSP: { + wl->next_af_subtype = P2P_PAF_GON_REQ; +- af_params->dwell_time = WL_MIN_DWELL_TIME; ++ /* increase dwell time to MED level */ ++ af_params->dwell_time = WL_MED_DWELL_TIME; + #ifdef WL_CFG80211_SYNC_GON + config_af_params->extra_listen = false; + #endif /* WL_CFG80211_SYNC_GON */ +@@ -4710,50 +4261,12 @@ wl_cfg80211_config_p2p_pub_af_tx(struct + return err; + } + +-#ifdef WL11U +-static bool +-wl_cfg80211_check_DFS_channel(struct wl_priv *wl, wl_af_params_t *af_params, +- void *frame, u16 frame_len) +-{ +- struct wl_scan_results *bss_list; +- struct wl_bss_info *bi = NULL; +- bool result = false; +- s32 i; +- +- /* If DFS channel is 52~148, check to block it or not */ +- if (af_params && +- (af_params->channel >= 52 && af_params->channel <= 148)) { +- if (!wl_cfgp2p_is_p2p_action(frame, frame_len)) { +- bss_list = wl->bss_list; +- bi = next_bss(bss_list, bi); +- for_each_bss(bss_list, bi, i) { +- if (CHSPEC_IS5G(bi->chanspec) && +- ((bi->ctl_ch ? bi->ctl_ch : CHSPEC_CHANNEL(bi->chanspec)) +- == af_params->channel)) { +- result = true; /* do not block the action frame */ +- break; +- } +- } +- } +- } +- else { +- result = true; +- } +- +- WL_DBG(("result=%s", result?"true":"false")); +- return result; +-} +-#endif /* WL11U */ +- + + static bool + wl_cfg80211_send_action_frame(struct wiphy *wiphy, struct net_device *dev, +- bcm_struct_cfgdev *cfgdev, wl_af_params_t *af_params, ++ struct net_device *ndev, wl_af_params_t *af_params, + wl_action_frame_t *action_frame, u16 action_frame_len, s32 bssidx) + { +-#ifdef WL11U +- struct net_device *ndev = NULL; +-#endif /* WL11U */ + struct wl_priv *wl = wiphy_priv(wiphy); + bool ack = false; + u8 category, action; +@@ -4764,13 +4277,7 @@ wl_cfg80211_send_action_frame(struct wip + #endif + dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); + +-#ifdef WL11U +-#if defined(WL_CFG80211_P2P_DEV_IF) +- ndev = dev; +-#else +- ndev = ndev_to_cfgdev(cfgdev); +-#endif /* WL_CFG80211_P2P_DEV_IF */ +-#endif /* WL11U */ ++ wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len); + + category = action_frame->data[DOT11_ACTION_CAT_OFF]; + action = action_frame->data[DOT11_ACTION_ACT_OFF]; +@@ -4818,7 +4325,7 @@ wl_cfg80211_send_action_frame(struct wip + } else { + WL_DBG(("Unknown Frame: category 0x%x, action 0x%x, length %d\n", + category, action, action_frame_len)); +- } ++ } + } else if (category == P2P_AF_CATEGORY) { + /* do not configure anything. it will be sent with a default configuration */ + } else { +@@ -4842,6 +4349,7 @@ wl_cfg80211_send_action_frame(struct wip + } else { + config_af_params.search_channel = false; + } ++ + #ifdef WL11U + if (ndev == wl_to_prmry_ndev(wl)) + config_af_params.search_channel = false; +@@ -4850,20 +4358,14 @@ wl_cfg80211_send_action_frame(struct wip + #ifdef VSDB + /* if connecting on primary iface, sleep for a while before sending af tx for VSDB */ + if (wl_get_drv_status(wl, CONNECTING, wl_to_prmry_ndev(wl))) { +- OSL_SLEEP(50); ++ msleep(50); + } + #endif + + /* if scan is ongoing, abort current scan. */ + if (wl_get_drv_status_all(wl, SCANNING)) { +- wl_notify_escan_complete(wl, wl->escan_info.ndev, true, true); +- } +-#ifdef WL11U +- /* handling DFS channel exceptions */ +- if (!wl_cfg80211_check_DFS_channel(wl, af_params, action_frame->data, action_frame->len)) { +- return false; /* the action frame was blocked */ ++ wl_notify_escan_complete(wl, ndev, true, true); + } +-#endif /* WL11U */ + + /* set status and destination address before sending af */ + if (wl->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) { +@@ -4881,31 +4383,24 @@ wl_cfg80211_send_action_frame(struct wip + /* search peer's channel */ + if (config_af_params.search_channel) { + /* initialize afx_hdl */ +- if (wl_cfgp2p_find_idx(wl, dev, &wl->afx_hdl->bssidx) != BCME_OK) { +- WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); +- goto exit; +- } ++ wl->afx_hdl->bssidx = wl_cfgp2p_find_idx(wl, dev); + wl->afx_hdl->dev = dev; + wl->afx_hdl->retry = 0; + wl->afx_hdl->peer_chan = WL_INVALID; + + if (wl_cfg80211_af_searching_channel(wl, dev) == WL_INVALID) { + WL_ERR(("couldn't find peer's channel.\n")); +- wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len, +- af_params->channel); + goto exit; + } + +- wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev); +- /* +- * Abort scan even for VSDB scenarios. Scan gets aborted in firmware +- * but after the check of piggyback algorithm. +- * To take care of current piggback algo, lets abort the scan here itself. +- */ +- wl_notify_escan_complete(wl, dev, true, true); + /* Suspend P2P discovery's search-listen to prevent it from + * starting a scan or changing the channel. + */ ++ wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev); ++/* Do not abort scan for VSDB. Scan will be aborted in firmware if necessary */ ++#ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST ++ wl_notify_escan_complete(wl, dev, true, true); ++#endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */ + wl_cfgp2p_discover_enable_search(wl, false); + + /* update channel */ +@@ -4916,8 +4411,6 @@ wl_cfg80211_send_action_frame(struct wip + off_chan_started_jiffies = jiffies; + #endif /* VSDB */ + +- wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len, af_params->channel); +- + /* Now send a tx action frame */ + ack = wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx) ? false : true; + +@@ -4929,8 +4422,7 @@ wl_cfg80211_send_action_frame(struct wip + OFF_CHAN_TIME_THRESHOLD_MS) { + WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(wl); + off_chan_started_jiffies = jiffies; +- } else +- OSL_SLEEP(AF_RETRY_DELAY_TIME); ++ } + } + #endif /* VSDB */ + ack = wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx) ? +@@ -4987,16 +4479,8 @@ exit: + return ack; + } + +-#define MAX_NUM_OF_ASSOCIATED_DEV 64 +-#if defined(WL_CFG80211_P2P_DEV_IF) +-static s32 +-wl_cfg80211_mgmt_tx(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev, +- struct ieee80211_channel *channel, bool offchan, +- unsigned int wait, const u8* buf, size_t len, bool no_cck, +- bool dont_wait_for_ack, u64 *cookie) +-#else + static s32 +-wl_cfg80211_mgmt_tx(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev, ++wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, + struct ieee80211_channel *channel, bool offchan, + enum nl80211_channel_type channel_type, + bool channel_type_valid, unsigned int wait, +@@ -5008,7 +4492,6 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, + bool dont_wait_for_ack, + #endif + u64 *cookie) +-#endif /* WL_CFG80211_P2P_DEV_IF */ + { + wl_action_frame_t *action_frame; + wl_af_params_t *af_params; +@@ -5024,12 +4507,19 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, + + WL_DBG(("Enter \n")); + +- dev = cfgdev_to_wlc_ndev(cfgdev, wl); ++ if (ndev == wl->p2p_net) { ++ dev = wl_to_prmry_ndev(wl); ++ } else { ++ /* If TX req is for any valid ifidx. Use as is */ ++ dev = ndev; ++ } ++ ++ /* find bssidx based on ndev */ ++ bssidx = wl_cfgp2p_find_idx(wl, dev); ++ if (bssidx == -1) { + +- /* find bssidx based on dev */ +- if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { +- WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); +- return BCME_ERROR; ++ WL_ERR(("Can not find the bssidx for dev( %p )\n", dev)); ++ return -ENODEV; + } + if (p2p_is_on(wl)) { + /* Suspend P2P discovery search-listen to prevent it from changing the +@@ -5052,40 +4542,23 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, + s32 ie_len = len - ie_offset; + if (dev == wl_to_prmry_ndev(wl)) + bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE); +- wl_cfgp2p_set_management_ie(wl, dev, bssidx, ++ wl_cfgp2p_set_management_ie(wl, dev, bssidx, + VNDR_IE_PRBRSP_FLAG, (u8 *)(buf + ie_offset), ie_len); +- cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, true, GFP_KERNEL); ++ cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, true, GFP_KERNEL); + goto exit; + } else if (ieee80211_is_disassoc(mgmt->frame_control) || + ieee80211_is_deauth(mgmt->frame_control)) { +- char mac_buf[MAX_NUM_OF_ASSOCIATED_DEV * +- sizeof(struct ether_addr) + sizeof(uint)] = {0}; +- int num_associated = 0; +- struct maclist *assoc_maclist = (struct maclist *)mac_buf; +- if (!bcmp((const uint8 *)BSSID_BROADCAST, +- (const struct ether_addr *)mgmt->da, ETHER_ADDR_LEN)) { +- assoc_maclist->count = MAX_NUM_OF_ASSOCIATED_DEV; +- err = wldev_ioctl(dev, WLC_GET_ASSOCLIST, +- assoc_maclist, sizeof(mac_buf), false); +- if (err < 0) +- WL_ERR(("WLC_GET_ASSOCLIST error %d\n", err)); +- else +- num_associated = assoc_maclist->count; +- } + memcpy(scb_val.ea.octet, mgmt->da, ETH_ALEN); + scb_val.val = mgmt->u.disassoc.reason_code; + err = wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val, + sizeof(scb_val_t), true); + if (err < 0) + WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON error %d\n", err)); +- WL_ERR(("Disconnect STA : %s scb_val.val %d\n", ++ WL_DBG(("Disconnect STA : %s scb_val.val %d\n", + bcm_ether_ntoa((const struct ether_addr *)mgmt->da, eabuf), + scb_val.val)); +- +- if (num_associated > 0 && ETHER_ISBCAST(mgmt->da)) +- wl_delay(400); +- +- cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, true, GFP_KERNEL); ++ wl_delay(400); ++ cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, true, GFP_KERNEL); + goto exit; + + } else if (ieee80211_is_action(mgmt->frame_control)) { +@@ -5146,9 +4619,10 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, + + memcpy(action_frame->data, &buf[DOT11_MGMT_HDR_LEN], action_frame->len); + +- ack = wl_cfg80211_send_action_frame(wiphy, dev, cfgdev, af_params, ++ ack = wl_cfg80211_send_action_frame(wiphy, dev, ndev, af_params, + action_frame, action_frame->len, bssidx); +- cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, ack, GFP_KERNEL); ++ ++ cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, ack, GFP_KERNEL); + + kfree(af_params); + exit: +@@ -5157,11 +4631,11 @@ exit: + + + static void +-wl_cfg80211_mgmt_frame_register(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev, ++wl_cfg80211_mgmt_frame_register(struct wiphy *wiphy, struct net_device *dev, + u16 frame_type, bool reg) + { + +- WL_DBG(("frame_type: %x, reg: %d\n", frame_type, reg)); ++ WL_DBG(("%s: frame_type: %x, reg: %d\n", __func__, frame_type, reg)); + + if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ)) + return; +@@ -5214,7 +4688,9 @@ wl_cfg80211_set_channel(struct wiphy *wi + } param = {0, 0}; + struct wl_priv *wl = wiphy_priv(wiphy); + +- dev = ndev_to_wlc_ndev(dev, wl); ++ if (wl->p2p_net == dev) { ++ dev = wl_to_prmry_ndev(wl); ++ } + _chan = ieee80211_frequency_to_channel(chan->center_freq); + WL_ERR(("netdev_ifidx(%d), chan_type(%d) target channel(%d) \n", + dev->ifindex, channel_type, _chan)); +@@ -5352,6 +4828,11 @@ wl_validate_wpa2ie(struct net_device *de + case WPA_CIPHER_AES_CCM: + gval = AES_ENABLED; + break; ++#ifdef BCMWAPI_WPI ++ case WAPI_CIPHER_SMS4: ++ gval = SMS4_ENABLED; ++ break; ++#endif + default: + WL_ERR(("No Security Info\n")); + break; +@@ -5376,6 +4857,11 @@ wl_validate_wpa2ie(struct net_device *de + case WPA_CIPHER_AES_CCM: + pval = AES_ENABLED; + break; ++#ifdef BCMWAPI_WPI ++ case WAPI_CIPHER_SMS4: ++ pval = SMS4_ENABLED; ++ break; ++#endif + default: + WL_ERR(("No Security Info\n")); + } +@@ -5754,9 +5240,6 @@ wl_cfg80211_bcn_bringup_ap( + s32 infra = 1; + s32 join_params_size = 0; + s32 ap = 1; +-#ifdef DISABLE_11H_SOFTAP +- s32 spect = 0; +-#endif /* DISABLE_11H_SOFTAP */ + s32 err = BCME_OK; + + WL_DBG(("Enter dev_role: %d\n", dev_role)); +@@ -5782,9 +5265,6 @@ wl_cfg80211_bcn_bringup_ap( + goto exit; + } + +- /* Do abort scan before creating GO */ +- wl_cfg80211_scan_abort(wl); +- + if ((err = wl_cfgp2p_bss(wl, dev, bssidx, 1)) < 0) { + WL_ERR(("GO Bring up error %d\n", err)); + goto exit; +@@ -5808,14 +5288,6 @@ wl_cfg80211_bcn_bringup_ap( + WL_ERR(("setting AP mode failed %d \n", err)); + goto exit; + } +-#ifdef DISABLE_11H_SOFTAP +- err = wldev_ioctl(dev, WLC_SET_SPECT_MANAGMENT, +- &spect, sizeof(s32), true); +- if (err < 0) { +- WL_ERR(("SET SPECT_MANAGMENT error %d\n", err)); +- goto exit; +- } +-#endif /* DISABLE_11H_SOFTAP */ + + err = wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), true); + if (unlikely(err)) { +@@ -5846,18 +5318,20 @@ exit: + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) + s32 +-wl_cfg80211_parse_ap_ies( ++wl_cfg80211_parse_set_ies( + struct net_device *dev, + struct cfg80211_beacon_data *info, +- struct parsed_ies *ies) ++ struct parsed_ies *ies, ++ u32 dev_role, ++ s32 bssidx) + { +- struct parsed_ies prb_ies; + struct wl_priv *wl = wlcfg_drv_priv; +- dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); +- u8 *vndr = NULL; +- u32 vndr_ie_len = 0; ++ struct parsed_ies prb_ies; + s32 err = BCME_OK; + ++ memset(ies, 0, sizeof(struct parsed_ies)); ++ memset(&prb_ies, 0, sizeof(struct parsed_ies)); ++ + /* Parse Beacon IEs */ + if (wl_cfg80211_parse_ies((u8 *)info->tail, + info->tail_len, ies) < 0) { +@@ -5866,74 +5340,34 @@ wl_cfg80211_parse_ap_ies( + goto fail; + } + +- vndr = (u8 *)info->proberesp_ies; +- vndr_ie_len = info->proberesp_ies_len; +- +- if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) { +- /* SoftAP mode */ +- struct ieee80211_mgmt *mgmt; +- mgmt = (struct ieee80211_mgmt *)info->probe_resp; +- if (mgmt != NULL) { +- vndr = (u8 *)&mgmt->u.probe_resp.variable; +- vndr_ie_len = info->probe_resp_len - +- offsetof(struct ieee80211_mgmt, u.probe_resp.variable); +- } ++ /* Set Beacon IEs to FW */ ++ if ((err = wl_cfgp2p_set_management_ie(wl, dev, bssidx, ++ VNDR_IE_BEACON_FLAG, (u8 *)info->tail, ++ info->tail_len)) < 0) { ++ WL_ERR(("Set Beacon IE Failed \n")); ++ } else { ++ WL_DBG(("Applied Vndr IEs for Beacon \n")); + } + + /* Parse Probe Response IEs */ +- if (wl_cfg80211_parse_ies(vndr, vndr_ie_len, &prb_ies) < 0) { +- WL_ERR(("PROBE RESP get IEs failed \n")); ++ if (wl_cfg80211_parse_ies((u8 *)info->proberesp_ies, ++ info->proberesp_ies_len, &prb_ies) < 0) { ++ WL_ERR(("PRB RESP get IEs failed \n")); + err = -EINVAL; +- } +- +-fail: +- +- return err; +-} +- +-s32 +-wl_cfg80211_set_ies( +- struct net_device *dev, +- struct cfg80211_beacon_data *info, +- s32 bssidx) +-{ +- struct wl_priv *wl = wlcfg_drv_priv; +- dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); +- u8 *vndr = NULL; +- u32 vndr_ie_len = 0; +- s32 err = BCME_OK; +- +- /* Set Beacon IEs to FW */ +- if ((err = wl_cfgp2p_set_management_ie(wl, dev, bssidx, +- VNDR_IE_BEACON_FLAG, (u8 *)info->tail, +- info->tail_len)) < 0) { +- WL_ERR(("Set Beacon IE Failed \n")); +- } else { +- WL_DBG(("Applied Vndr IEs for Beacon \n")); +- } +- +- vndr = (u8 *)info->proberesp_ies; +- vndr_ie_len = info->proberesp_ies_len; +- +- if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) { +- /* SoftAP mode */ +- struct ieee80211_mgmt *mgmt; +- mgmt = (struct ieee80211_mgmt *)info->probe_resp; +- if (mgmt != NULL) { +- vndr = (u8 *)&mgmt->u.probe_resp.variable; +- vndr_ie_len = info->probe_resp_len - +- offsetof(struct ieee80211_mgmt, u.probe_resp.variable); +- } ++ goto fail; + } + + /* Set Probe Response IEs to FW */ + if ((err = wl_cfgp2p_set_management_ie(wl, dev, bssidx, +- VNDR_IE_PRBRSP_FLAG, vndr, vndr_ie_len)) < 0) { ++ VNDR_IE_PRBRSP_FLAG, (u8 *)info->proberesp_ies, ++ info->proberesp_ies_len)) < 0) { + WL_ERR(("Set Probe Resp IE Failed \n")); + } else { + WL_DBG(("Applied Vndr IEs for Probe Resp \n")); + } + ++fail: ++ + return err; + } + #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) */ +@@ -6006,6 +5440,8 @@ static s32 wl_cfg80211_hostapd_sec( + return 0; + } + ++#if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \ ++ 2, 0)) + static s32 + wl_cfg80211_del_station( + struct wiphy *wiphy, +@@ -6016,11 +5452,6 @@ wl_cfg80211_del_station( + struct wl_priv *wl = wiphy_priv(wiphy); + scb_val_t scb_val; + s8 eabuf[ETHER_ADDR_STR_LEN]; +- int err; +- char mac_buf[MAX_NUM_OF_ASSOCIATED_DEV * +- sizeof(struct ether_addr) + sizeof(uint)] = {0}; +- struct maclist *assoc_maclist = (struct maclist *)mac_buf; +- int num_associated = 0; + + WL_DBG(("Entry\n")); + if (mac_addr == NULL) { +@@ -6028,7 +5459,11 @@ wl_cfg80211_del_station( + return 0; + } + +- dev = ndev_to_wlc_ndev(ndev, wl); ++ if (ndev == wl->p2p_net) { ++ dev = wl_to_prmry_ndev(wl); ++ } else { ++ dev = ndev; ++ } + + if (p2p_is_on(wl)) { + /* Suspend P2P discovery search-listen to prevent it from changing the +@@ -6040,28 +5475,18 @@ wl_cfg80211_del_station( + } + } + +- assoc_maclist->count = MAX_NUM_OF_ASSOCIATED_DEV; +- err = wldev_ioctl(ndev, WLC_GET_ASSOCLIST, +- assoc_maclist, sizeof(mac_buf), false); +- if (err < 0) +- WL_ERR(("WLC_GET_ASSOCLIST error %d\n", err)); +- else +- num_associated = assoc_maclist->count; +- + memcpy(scb_val.ea.octet, mac_addr, ETHER_ADDR_LEN); + scb_val.val = DOT11_RC_DEAUTH_LEAVING; +- err = wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val, +- sizeof(scb_val_t), true); +- if (err < 0) +- WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON err %d\n", err)); +- WL_ERR(("Disconnect STA : %s scb_val.val %d\n", ++ if (wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val, ++ sizeof(scb_val_t), true)) ++ WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON failed\n")); ++ WL_DBG(("Disconnect STA : %s scb_val.val %d\n", + bcm_ether_ntoa((const struct ether_addr *)mac_addr, eabuf), + scb_val.val)); +- +- if (num_associated > 0 && ETHER_ISBCAST(mac_addr)) +- wl_delay(400); ++ wl_delay(400); + return 0; + } ++#endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VER >= KERNEL_VERSION(3, 2, 0)) */ + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) + static s32 +@@ -6080,19 +5505,14 @@ wl_cfg80211_start_ap( + if (dev == wl_to_prmry_ndev(wl)) { + WL_DBG(("Start AP req on primary iface: Softap\n")); + dev_role = NL80211_IFTYPE_AP; +- } +-#if defined(WL_ENABLE_P2P_IF) +- else if (dev == wl->p2p_net) { ++ } else if (dev == wl->p2p_net) { + /* Group Add request on p2p0 */ + WL_DBG(("Start AP req on P2P iface: GO\n")); + dev = wl_to_prmry_ndev(wl); + dev_role = NL80211_IFTYPE_P2P_GO; + } +-#endif /* WL_ENABLE_P2P_IF */ +- if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { +- WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); +- return BCME_ERROR; +- } ++ ++ bssidx = wl_cfgp2p_find_idx(wl, dev); + if (p2p_is_on(wl) && + (bssidx == wl_to_p2p_bss_bssidx(wl, + P2PAPI_BSSCFG_CONNECTION))) { +@@ -6100,26 +5520,15 @@ wl_cfg80211_start_ap( + WL_DBG(("Start AP req on P2P connection iface\n")); + } + +- if (!check_dev_role_integrity(wl, dev_role)) +- goto fail; +- +-#if defined(WL_CFG80211_P2P_DEV_IF) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) +- if ((err = wl_cfg80211_set_channel(wiphy, dev, +- dev->ieee80211_ptr->preset_chandef.chan, +- NL80211_CHAN_HT20) < 0)) { +- WL_ERR(("Set channel failed \n")); +- goto fail; +- } +-#endif /* WL_CFG80211_P2P_DEV_IF || (LINUX_VERSION >= VERSION(3, 6, 0)) */ +- + if ((err = wl_cfg80211_bcn_set_params(info, dev, + dev_role, bssidx)) < 0) { + WL_ERR(("Beacon params set failed \n")); + goto fail; + } + +- /* Parse IEs */ +- if ((err = wl_cfg80211_parse_ap_ies(dev, &info->beacon, &ies)) < 0) { ++ /* Set IEs to FW */ ++ if ((err = wl_cfg80211_parse_set_ies(dev, &info->beacon, ++ &ies, dev_role, bssidx) < 0)) { + WL_ERR(("Set IEs failed \n")); + goto fail; + } +@@ -6139,10 +5548,6 @@ wl_cfg80211_start_ap( + + WL_DBG(("** AP/GO Created **\n")); + +- /* Set IEs to FW */ +- if ((err = wl_cfg80211_set_ies(dev, &info->beacon, bssidx)) < 0) +- WL_ERR(("Set IEs failed \n")); +- + fail: + if (err) { + WL_ERR(("ADD/SET beacon failed\n")); +@@ -6167,42 +5572,33 @@ wl_cfg80211_stop_ap( + WL_DBG(("Enter \n")); + if (dev == wl_to_prmry_ndev(wl)) { + dev_role = NL80211_IFTYPE_AP; +- } +-#if defined(WL_ENABLE_P2P_IF) +- else if (dev == wl->p2p_net) { ++ } else if (dev == wl->p2p_net) { + /* Group Add request on p2p0 */ + dev = wl_to_prmry_ndev(wl); + dev_role = NL80211_IFTYPE_P2P_GO; + } +-#endif /* WL_ENABLE_P2P_IF */ +- if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { +- WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); +- return BCME_ERROR; +- } ++ bssidx = wl_cfgp2p_find_idx(wl, dev); + if (p2p_is_on(wl) && + (bssidx == wl_to_p2p_bss_bssidx(wl, + P2PAPI_BSSCFG_CONNECTION))) { + dev_role = NL80211_IFTYPE_P2P_GO; + } + +- if (!check_dev_role_integrity(wl, dev_role)) +- goto exit; +- + if (dev_role == NL80211_IFTYPE_AP) { + /* SoftAp on primary Interface. + * Shut down AP and turn on MPC + */ +- if ((err = wldev_ioctl(dev, WLC_SET_AP, &ap, sizeof(s32), true)) < 0) { +- WL_ERR(("setting AP mode failed %d \n", err)); +- err = -ENOTSUPP; +- goto exit; +- } + err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true); + if (err < 0) { + WL_ERR(("SET INFRA error %d\n", err)); + err = -ENOTSUPP; + goto exit; + } ++ if ((err = wldev_ioctl(dev, WLC_SET_AP, &ap, sizeof(s32), true)) < 0) { ++ WL_ERR(("setting AP mode failed %d \n", err)); ++ err = -ENOTSUPP; ++ goto exit; ++ } + + err = wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), true); + if (unlikely(err)) { +@@ -6214,17 +5610,8 @@ wl_cfg80211_stop_ap( + wl_clr_drv_status(wl, AP_CREATED, dev); + /* Turn on the MPC */ + wldev_iovar_setint(dev, "mpc", 1); +- if (wl->ap_info) { +- kfree(wl->ap_info->wpa_ie); +- kfree(wl->ap_info->rsn_ie); +- kfree(wl->ap_info->wps_ie); +- kfree(wl->ap_info); +- wl->ap_info = NULL; +- } + } else { + WL_DBG(("Stopping P2P GO \n")); +- DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE((dhd_pub_t *)(wl->pub), DHD_EVENT_TIMEOUT_MS*3); +- DHD_OS_WAKE_LOCK_TIMEOUT((dhd_pub_t *)(wl->pub)); + } + + exit: +@@ -6247,35 +5634,22 @@ wl_cfg80211_change_beacon( + + if (dev == wl_to_prmry_ndev(wl)) { + dev_role = NL80211_IFTYPE_AP; +- } +-#if defined(WL_ENABLE_P2P_IF) +- else if (dev == wl->p2p_net) { ++ } else if (dev == wl->p2p_net) { + /* Group Add request on p2p0 */ + dev = wl_to_prmry_ndev(wl); + dev_role = NL80211_IFTYPE_P2P_GO; + } +-#endif /* WL_ENABLE_P2P_IF */ +- if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { +- WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); +- return BCME_ERROR; +- } ++ ++ bssidx = wl_cfgp2p_find_idx(wl, dev); + if (p2p_is_on(wl) && + (bssidx == wl_to_p2p_bss_bssidx(wl, + P2PAPI_BSSCFG_CONNECTION))) { + dev_role = NL80211_IFTYPE_P2P_GO; + } + +- if (!check_dev_role_integrity(wl, dev_role)) +- goto fail; +- +- /* Parse IEs */ +- if ((err = wl_cfg80211_parse_ap_ies(dev, info, &ies)) < 0) { +- WL_ERR(("Parse IEs failed \n")); +- goto fail; +- } +- + /* Set IEs to FW */ +- if ((err = wl_cfg80211_set_ies(dev, info, bssidx)) < 0) { ++ if ((err = wl_cfg80211_parse_set_ies(dev, info, ++ &ies, dev_role, bssidx) < 0)) { + WL_ERR(("Set IEs failed \n")); + goto fail; + } +@@ -6304,32 +5678,25 @@ wl_cfg80211_add_set_beacon(struct wiphy + struct parsed_ies ies; + bcm_tlv_t *ssid_ie; + bool pbc = 0; ++ + WL_DBG(("interval (%d) dtim_period (%d) head_len (%d) tail_len (%d)\n", + info->interval, info->dtim_period, info->head_len, info->tail_len)); + + if (dev == wl_to_prmry_ndev(wl)) { + dev_role = NL80211_IFTYPE_AP; +- } +-#if defined(WL_ENABLE_P2P_IF) +- else if (dev == wl->p2p_net) { ++ } else if (dev == wl->p2p_net) { + /* Group Add request on p2p0 */ + dev = wl_to_prmry_ndev(wl); + dev_role = NL80211_IFTYPE_P2P_GO; + } +-#endif /* WL_ENABLE_P2P_IF */ +- if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { +- WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); +- return BCME_ERROR; +- } ++ ++ bssidx = wl_cfgp2p_find_idx(wl, dev); + if (p2p_is_on(wl) && + (bssidx == wl_to_p2p_bss_bssidx(wl, + P2PAPI_BSSCFG_CONNECTION))) { + dev_role = NL80211_IFTYPE_P2P_GO; + } + +- if (!check_dev_role_integrity(wl, dev_role)) +- goto fail; +- + ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN; + /* find the SSID */ + if ((ssid_ie = bcm_parse_tlvs((u8 *)&info->head[ie_offset], +@@ -6424,8 +5791,7 @@ fail: + #define PNO_TIME 30 + #define PNO_REPEAT 4 + #define PNO_FREQ_EXPO_MAX 2 +-static int +-wl_cfg80211_sched_scan_start(struct wiphy *wiphy, ++int wl_cfg80211_sched_scan_start(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_sched_scan_request *request) + { +@@ -6476,11 +5842,17 @@ wl_cfg80211_sched_scan_start(struct wiph + } + + if (ssid_count) { +- if ((ret = dhd_dev_pno_set_for_ssid(dev, ssids_local, request->n_match_sets, +- pno_time, pno_repeat, pno_freq_expo_max, NULL, 0)) < 0) { ++ if ((ret = dhd_dev_pno_set(dev, ssids_local, request->n_match_sets, ++ pno_time, pno_repeat, pno_freq_expo_max)) < 0) { + WL_ERR(("PNO setup failed!! ret=%d \n", ret)); + return -EINVAL; + } ++ ++ /* Enable the PNO */ ++ if (dhd_dev_pno_enable(dev, 1) < 0) { ++ WL_ERR(("PNO enable failed!! ret=%d \n", ret)); ++ return -EINVAL; ++ } + wl->sched_scan_req = request; + } else { + return -EINVAL; +@@ -6489,16 +5861,18 @@ wl_cfg80211_sched_scan_start(struct wiph + return 0; + } + +-static int +-wl_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev) ++int wl_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev) + { + struct wl_priv *wl = wiphy_priv(wiphy); + + WL_DBG(("Enter \n")); + WL_PNO((">>> SCHED SCAN STOP\n")); + +- if (dhd_dev_pno_stop_for_ssid(dev) < 0) +- WL_ERR(("PNO Stop for SSID failed")); ++ if (dhd_dev_pno_enable(dev, 0) < 0) ++ WL_ERR(("PNO disable failed")); ++ ++ if (dhd_dev_pno_reset(dev) < 0) ++ WL_ERR(("PNO reset failed")); + + if (wl->scan_request && wl->sched_scan_running) { + WL_PNO((">>> Sched scan running. Aborting it..\n")); +@@ -6516,10 +5890,6 @@ static struct cfg80211_ops wl_cfg80211_o + .add_virtual_intf = wl_cfg80211_add_virtual_iface, + .del_virtual_intf = wl_cfg80211_del_virtual_iface, + .change_virtual_intf = wl_cfg80211_change_virtual_iface, +-#if defined(WL_CFG80211_P2P_DEV_IF) +- .start_p2p_device = wl_cfgp2p_start_p2p_device, +- .stop_p2p_device = wl_cfgp2p_stop_p2p_device, +-#endif /* WL_CFG80211_P2P_DEV_IF */ + .scan = wl_cfg80211_scan, + .set_wiphy_params = wl_cfg80211_set_wiphy_params, + .join_ibss = wl_cfg80211_join_ibss, +@@ -6545,10 +5915,8 @@ static struct cfg80211_ops wl_cfg80211_o + .mgmt_tx = wl_cfg80211_mgmt_tx, + .mgmt_frame_register = wl_cfg80211_mgmt_frame_register, + .change_bss = wl_cfg80211_change_bss, +-#if !defined(WL_CFG80211_P2P_DEV_IF) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) + .set_channel = wl_cfg80211_set_channel, +-#endif /* !WL_CFG80211_P2P_DEV_IF && (LINUX_VERSION < VERSION(3, 6, 0)) */ +-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) + .set_beacon = wl_cfg80211_add_set_beacon, + .add_beacon = wl_cfg80211_add_set_beacon, + #else +@@ -6560,11 +5928,11 @@ static struct cfg80211_ops wl_cfg80211_o + .sched_scan_start = wl_cfg80211_sched_scan_start, + .sched_scan_stop = wl_cfg80211_sched_scan_stop, + #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) */ ++#if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \ ++ 2, 0)) + .del_station = wl_cfg80211_del_station, + .mgmt_tx_cancel_wait = wl_cfg80211_mgmt_tx_cancel_wait, +-#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0) +- .tdls_oper = wl_cfg80211_tdls_oper +-#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0) */ ++#endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VERSION >= (3,2,0) */ + }; + + s32 wl_mode_to_nl80211_iftype(s32 mode) +@@ -6585,17 +5953,13 @@ s32 wl_mode_to_nl80211_iftype(s32 mode) + return err; + } + +-#ifdef CONFIG_CFG80211_INTERNAL_REGDB +-/* Kernel Network Support->Wireless->Regulatory rules database +- options should be enabled and regulatory CRDA regdb table populated in Kernel +- for proper country reg notification +-*/ + static int + wl_cfg80211_reg_notifier( + struct wiphy *wiphy, + struct regulatory_request *request) + { + struct wl_priv *wl = (struct wl_priv *)wiphy_priv(wiphy); ++ wl_country_t cspec = {{0}, 0, {0} }; + int ret = 0; + + if (!request || !wl) { +@@ -6607,36 +5971,44 @@ wl_cfg80211_reg_notifier( + request->alpha2[0], request->alpha2[1], request->initiator)); + + /* We support only REGDOM_SET_BY_USER as of now */ +- if ((request->initiator != NL80211_REGDOM_SET_BY_USER) && +- (request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE)) { +- WL_ERR(("reg_notifier for intiator:%d not supported : set default\n", ++ if (request->initiator != NL80211_REGDOM_SET_BY_USER) { ++ WL_ERR(("reg_notifier for intiator:%d not supported \n", + request->initiator)); +- /* in case of no supported country by regdb +- lets driver setup platform default Locale +- */ ++ return -ENOTSUPP; + } + +- WL_ERR(("Set country code %c%c from %s\n", +- request->alpha2[0], request->alpha2[1], +- ((request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) ? " 11d AP" : "User"))); ++ if (request->alpha2[0] == '0' && request->alpha2[1] == '0') { ++ /* world domain */ ++ WL_ERR(("World domain. Setting XY/4 \n")); ++ strncpy(cspec.country_abbrev, "XY", strlen("XY")); ++ cspec.rev = 4; ++ } else { ++ memcpy(cspec.country_abbrev, request->alpha2, 2); ++ cspec.country_abbrev[3] = '\0'; ++ cspec.rev = -1; /* Unspecified */ ++ } + +- if ((ret = wldev_set_country(wl_to_prmry_ndev(wl), request->alpha2, +- false, (request->initiator == NL80211_REGDOM_SET_BY_USER ? true : false))) < 0) { ++ if ((ret = wldev_iovar_setbuf(wl_to_prmry_ndev(wl), "country", (char *)&cspec, ++ sizeof(cspec), wl->ioctl_buf, WLC_IOCTL_SMLEN, NULL)) < 0) { + WL_ERR(("set country Failed :%d\n", ret)); ++ goto exit; + } + ++ if ((ret = wl_update_wiphybands(wl, false)) < 0) { ++ WL_ERR(("wl_update_wiphybands failed\n")); ++ goto exit; ++ } ++ ++ WL_DBG(("%s: set country '%s/%d' done\n", ++ __FUNCTION__, cspec.country_abbrev, cspec.rev)); ++ ++exit: + return ret; + } +-#endif /* CONFIG_CFG80211_INTERNAL_REGDB */ + +-static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev, void *data) ++static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev) + { + s32 err = 0; +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \ +- (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF)) +- dhd_pub_t *dhd = (dhd_pub_t *)data; +-#endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */ +- + wdev->wiphy = + wiphy_new(&wl_cfg80211_ops, sizeof(struct wl_priv)); + if (unlikely(!wdev->wiphy)) { +@@ -6657,34 +6029,11 @@ static s32 wl_setup_wiphy(struct wireles + #endif /* WL_SCHED_SCAN */ + wdev->wiphy->interface_modes = + BIT(NL80211_IFTYPE_STATION) +- | BIT(NL80211_IFTYPE_ADHOC) +-#if !defined(WL_ENABLE_P2P_IF) ++#if !(defined(WLP2P) && defined(WL_ENABLE_P2P_IF)) + | BIT(NL80211_IFTYPE_MONITOR) +-#endif /* !WL_ENABLE_P2P_IF */ +-#if defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF) +- | BIT(NL80211_IFTYPE_P2P_CLIENT) +- | BIT(NL80211_IFTYPE_P2P_GO) +-#endif /* WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF */ +-#if defined(WL_CFG80211_P2P_DEV_IF) +- | BIT(NL80211_IFTYPE_P2P_DEVICE) +-#endif /* WL_CFG80211_P2P_DEV_IF */ ++#endif + | BIT(NL80211_IFTYPE_AP); + +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \ +- (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF)) +- if (dhd && dhd->op_mode == DHD_FLAG_HOSTAP_MODE) { +- WL_DBG(("Setting interface combinations for SoftAP mode\n")); +- wdev->wiphy->iface_combinations = softap_iface_combinations; +- wdev->wiphy->n_iface_combinations = +- ARRAY_SIZE(softap_iface_combinations); +- } else { +- WL_DBG(("Setting interface combinations for STA+P2P mode\n")); +- wdev->wiphy->iface_combinations = sta_p2p_iface_combinations; +- wdev->wiphy->n_iface_combinations = +- ARRAY_SIZE(sta_p2p_iface_combinations); +- } +-#endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */ +- + wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; + + wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; +@@ -6713,26 +6062,22 @@ static s32 wl_setup_wiphy(struct wireles + * if needed so DON'T advertise that featur eto Supplicant. + */ + #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) +-/* wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM; */ ++ /* wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM; */ + #endif + #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0) + wdev->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | + WIPHY_FLAG_OFFCHAN_TX; + #endif +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) ++#if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \ ++ 4, 0)) + /* From 3.4 kernel ownards AP_SME flag can be advertised + * to remove the patch from supplicant + */ + wdev->wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME; +-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) */ ++#endif + +-#ifdef CONFIG_CFG80211_INTERNAL_REGDB + wdev->wiphy->reg_notifier = wl_cfg80211_reg_notifier; +-#endif /* CONFIG_CFG80211_INTERNAL_REGDB */ + +-#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0)) || 0 +- wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS; +-#endif + WL_DBG(("Registering custom regulatory)\n")); + wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; + wiphy_apply_custom_regulatory(wdev->wiphy, &brcm_regdom); +@@ -6742,12 +6087,6 @@ static s32 wl_setup_wiphy(struct wireles + WL_ERR(("Couldn not register wiphy device (%d)\n", err)); + wiphy_free(wdev->wiphy); + } +- +-#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && (LINUX_VERSION_CODE <= \ +- KERNEL_VERSION(3, 3, 0))) && defined(WL_IFACE_COMB_NUM_CHANNELS) +- wdev->wiphy->flags &= ~WIPHY_FLAG_ENFORCE_COMBINATIONS; +-#endif /* ((LINUX_VER >= 3.0) && (LINUX_VER <= 3.3)) && WL_IFACE_COMB_NUM_CHANNELS */ +- + return err; + } + +@@ -6770,25 +6109,81 @@ static void wl_free_wdev(struct wl_priv + */ + } + ++#if defined(RSSIAVG) ++static wl_rssi_cache_ctrl_t g_rssi_cache_ctrl; ++#endif ++#if defined(BSSCACHE) ++static wl_bss_cache_ctrl_t g_bss_cache_ctrl; ++#endif ++ + static s32 wl_inform_bss(struct wl_priv *wl) + { + struct wl_scan_results *bss_list; + struct wl_bss_info *bi = NULL; /* must be initialized */ + s32 err = 0; + s32 i; ++#if defined(RSSIAVG) ++ struct net_device *ndev = wl_to_prmry_ndev(wl); ++#endif ++#if defined(BSSCACHE) ++ wl_bss_cache_t *node; ++#endif + + bss_list = wl->bss_list; +- WL_DBG(("scanned AP count (%d)\n", bss_list->count)); ++#if defined(BSSCACHE) ++ if (g_bss_cache_ctrl.m_timer_expired || (p2p_is_on(wl) && p2p_scan(wl))) { ++#if defined(RSSIAVG) ++ wl_free_rssi_cache(&g_rssi_cache_ctrl); ++#endif ++ wl_free_bss_cache(&g_bss_cache_ctrl); ++ g_bss_cache_ctrl.m_timer_expired ^= 1; ++ } ++ wl_update_bss_cache(&g_bss_cache_ctrl, bss_list); ++ wl_delete_dirty_bss_cache(&g_bss_cache_ctrl); ++ wl_reset_bss_cache(&g_bss_cache_ctrl); ++#endif ++ ++#if defined(RSSIAVG) ++#if defined(BSSCACHE) ++ node = g_bss_cache_ctrl.m_cache_head; ++ for (;node;) { ++ wl_update_rssi_cache(&g_rssi_cache_ctrl, &node->results); ++ node = node->next; ++ } ++#else ++ wl_update_rssi_cache(&g_rssi_cache_ctrl, bss_list); ++#endif ++ if (!in_atomic()) ++ wl_update_connected_rssi_cache(&g_rssi_cache_ctrl, ndev); ++ wl_delete_dirty_rssi_cache(&g_rssi_cache_ctrl); ++ wl_reset_rssi_cache(&g_rssi_cache_ctrl); ++#endif ++ ++ WL_SCAN(("scanned AP count (%d)\n", bss_list->count)); ++ ++#if defined(BSSCACHE) ++ node = g_bss_cache_ctrl.m_cache_head; ++ for (i=0; node && iresults.bss_info; ++ err = wl_inform_single_bss(wl, bi, 0); ++ if (unlikely(err)) ++ break; ++ node = node->next; ++ } ++ wl_run_bss_cache_timer(&g_bss_cache_ctrl, 0); ++ wl_run_bss_cache_timer(&g_bss_cache_ctrl, 1); ++#else + bi = next_bss(bss_list, bi); + for_each_bss(bss_list, bi, i) { +- err = wl_inform_single_bss(wl, bi); ++ err = wl_inform_single_bss(wl, bi, 0); + if (unlikely(err)) + break; + } ++#endif + return err; + } + +-static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi) ++static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi, u8 is_roam_done) + { + struct wiphy *wiphy = wl_to_wiphy(wl); + struct ieee80211_mgmt *mgmt; +@@ -6803,6 +6198,7 @@ static s32 wl_inform_single_bss(struct w + u32 freq; + s32 err = 0; + gfp_t aflags; ++ u8 *ie_offset = NULL; + + if (unlikely(dtoh32(bi->length) > WL_BSS_INFO_MAX)) { + WL_DBG(("Beacon is larger than buffer. Discarding\n")); +@@ -6828,7 +6224,13 @@ static s32 wl_inform_single_bss(struct w + kfree(notif_bss_info); + return -EINVAL; + } +- notif_bss_info->rssi = dtoh16(bi->RSSI) + RSSI_OFFSET; ++ notif_bss_info->rssi = dtoh16(bi->RSSI); ++#if defined(RSSIAVG) ++ notif_bss_info->rssi = wl_get_avg_rssi(&g_rssi_cache_ctrl, &bi->BSSID); ++#endif ++#if defined(RSSIOFFSET) ++ notif_bss_info->rssi = wl_update_rssi_offset(notif_bss_info->rssi); ++#endif + memcpy(mgmt->bssid, &bi->BSSID, ETHER_ADDR_LEN); + mgmt_type = wl->active_scan ? + IEEE80211_STYPE_PROBE_RESP : IEEE80211_STYPE_BEACON; +@@ -6842,13 +6244,42 @@ static s32 wl_inform_single_bss(struct w + beacon_proberesp->beacon_int = cpu_to_le16(bi->beacon_period); + beacon_proberesp->capab_info = cpu_to_le16(bi->capability); + wl_rst_ie(wl); +- wl_update_hidden_ap_ie(bi, ((u8 *) bi) + bi->ie_offset, &bi->ie_length); +- wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length); ++ ++ ie_offset = ((u8 *) bi) + bi->ie_offset; ++ ++ if (is_roam_done && ((int)(*(ie_offset)) == WLAN_EID_SSID && ++ ((int)(*(ie_offset+1)) == 0 || (int)(*(ie_offset+2)) == 0))) { ++ u8 *ie_new_offset = NULL; ++ uint8 ie_new_length; ++ ++ WL_ERR(("WAR trace: Changing the SSID Info, from beacon %d\n", ++ bi->flags & WL_BSS_FLAGS_FROM_BEACON)); ++ ++ ie_new_offset = (u8 *)kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL); ++ if (ie_new_offset) { ++ *(ie_new_offset) = WLAN_EID_SSID; ++ *(ie_new_offset+1) = bi->SSID_len; ++ memcpy(ie_new_offset+2, bi->SSID, bi->SSID_len); ++ ie_new_length = bi->ie_length - *(ie_offset+1) + bi->SSID_len; ++ ++ /* Copy the remaining IE apart from SSID IE from bi */ ++ memcpy(ie_new_offset+2 + bi->SSID_len, ++ ie_offset+2 + *(ie_offset+1), ++ bi->ie_length - 2 - *(ie_offset+1)); ++ wl_mrg_ie(wl, ie_new_offset, ie_new_length); ++ kfree(ie_new_offset); ++ } else { ++ wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length); ++ } ++ } else { ++ wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length); ++ } ++ + wl_cp_ie(wl, beacon_proberesp->variable, WL_BSS_INFO_MAX - + offsetof(struct wl_cfg80211_bss_info, frame_buf)); + notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt, + u.beacon.variable) + wl_get_ielen(wl); +-#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) ++#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS) + freq = ieee80211_channel_to_frequency(notif_bss_info->channel); + (void)band->band; + #else +@@ -6865,15 +6296,14 @@ static s32 wl_inform_single_bss(struct w + kfree(notif_bss_info); + return -EINVAL; + } +- WL_DBG(("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM" +- "mgmt_type %d frame_len %d\n", bi->SSID, +- notif_bss_info->rssi, notif_bss_info->channel, +- mgmt->u.beacon.capab_info, &bi->BSSID, mgmt_type, +- notif_bss_info->frame_len)); ++ WL_SCAN(("BSSID %pM, channel %d, rssi %d, capability 0x04%x, mgmt_type %d, " ++ "frame_len %d, SSID \"%s\"\n", &bi->BSSID, notif_bss_info->channel, ++ notif_bss_info->rssi, mgmt->u.beacon.capab_info, mgmt_type, ++ notif_bss_info->frame_len, bi->SSID)); + + signal = notif_bss_info->rssi * 100; + if (!mgmt->u.probe_resp.timestamp) { +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39) + struct timespec ts; + get_monotonic_boottime(&ts); + mgmt->u.probe_resp.timestamp = ((u64)ts.tv_sec*1000000) +@@ -6886,7 +6316,6 @@ static s32 wl_inform_single_bss(struct w + #endif + } + +- + cbss = cfg80211_inform_bss_frame(wiphy, channel, mgmt, + le16_to_cpu(notif_bss_info->frame_len), signal, aflags); + if (unlikely(!cbss)) { +@@ -6895,11 +6324,7 @@ static s32 wl_inform_single_bss(struct w + return -EINVAL; + } + +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)) +- cfg80211_put_bss(wiphy, cbss); +-#else + cfg80211_put_bss(cbss); +-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */ + kfree(notif_bss_info); + return err; + } +@@ -7068,7 +6493,7 @@ wl_notify_connect_status_ap(struct wl_pr + kfree(body); + return -EINVAL; + } +-#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) ++#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS) + freq = ieee80211_channel_to_frequency(channel); + (void)band->band; + #else +@@ -7106,6 +6531,7 @@ exit: + kfree(mgmt_frame); + if (body) + kfree(body); ++ return err; + #else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0) && !WL_CFG80211_STA_EVENT */ + sinfo.filled = 0; + if (((event == WLC_E_ASSOC_IND) || (event == WLC_E_REASSOC_IND)) && +@@ -7149,97 +6575,39 @@ wl_get_auth_assoc_status(struct wl_priv + } + + static s32 +-wl_notify_connect_status_ibss(struct wl_priv *wl, struct net_device *ndev, +- const wl_event_msg_t *e, void *data) +-{ +- s32 err = 0; +- u32 event = ntoh32(e->event_type); +- u16 flags = ntoh16(e->flags); +- u32 status = ntoh32(e->status); +- bool active; +- +- if (event == WLC_E_JOIN) { +- WL_DBG(("joined in IBSS network\n")); +- } +- if (event == WLC_E_START) { +- WL_DBG(("started IBSS network\n")); +- } +- if (event == WLC_E_JOIN || event == WLC_E_START || +- (event == WLC_E_LINK && (flags == WLC_EVENT_MSG_LINK))) { +- if (wl_get_drv_status(wl, CONNECTED, ndev)) { +- /* ROAM or Redundant */ +- u8 *cur_bssid = wl_read_prof(wl, ndev, WL_PROF_BSSID); +- if (memcmp(cur_bssid, &e->addr, ETHER_ADDR_LEN) == 0) { +- WL_DBG(("IBSS connected event from same BSSID(" +- MACDBG "), ignore it\n", MAC2STRDBG(cur_bssid))); +- return err; +- } +- WL_INFO(("IBSS BSSID is changed from " MACDBG " to " MACDBG "\n", +- MAC2STRDBG(cur_bssid), MAC2STRDBG((u8 *)&e->addr))); +- wl_get_assoc_ies(wl, ndev); +- wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID); +- wl_update_bss_info(wl, ndev); +- cfg80211_ibss_joined(ndev, (s8 *)&e->addr, GFP_KERNEL); +- } +- else { +- /* New connection */ +- WL_INFO(("IBSS connected to " MACDBG "\n", MAC2STRDBG((u8 *)&e->addr))); +- wl_link_up(wl); +- wl_get_assoc_ies(wl, ndev); +- wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID); +- wl_update_bss_info(wl, ndev); +- cfg80211_ibss_joined(ndev, (s8 *)&e->addr, GFP_KERNEL); +- wl_set_drv_status(wl, CONNECTED, ndev); +- active = true; +- wl_update_prof(wl, ndev, NULL, (void *)&active, WL_PROF_ACT); +- } +- } else if ((event == WLC_E_LINK && !(flags & WLC_EVENT_MSG_LINK)) || +- event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND) { +- wl_clr_drv_status(wl, CONNECTED, ndev); +- wl_link_down(wl); +- wl_init_prof(wl, ndev); +- } +- else if (event == WLC_E_SET_SSID && status == WLC_E_STATUS_NO_NETWORKS) { +- WL_DBG(("no action - join fail (IBSS mode)\n")); +- } +- else { +- WL_DBG(("no action (IBSS mode)\n")); +- } +- return err; +-} +- +-static s32 +-wl_notify_connect_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev, ++wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, + const wl_event_msg_t *e, void *data) + { + bool act; +- struct net_device *ndev = NULL; + s32 err = 0; + u32 event = ntoh32(e->event_type); + +- ndev = cfgdev_to_wlc_ndev(cfgdev, wl); +- + if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_AP) { +- err = wl_notify_connect_status_ap(wl, ndev, e, data); +- } else if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_IBSS) { +- err = wl_notify_connect_status_ibss(wl, ndev, e, data); +- } else if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_BSS) { ++ wl_notify_connect_status_ap(wl, ndev, e, data); ++ } else { + WL_DBG(("wl_notify_connect_status : event %d status : %d ndev %p\n", + ntoh32(e->event_type), ntoh32(e->status), ndev)); + if (event == WLC_E_ASSOC || event == WLC_E_AUTH) { + wl_get_auth_assoc_status(wl, ndev, e); +- return 0; ++ return err; + } + if (wl_is_linkup(wl, e, ndev)) { + wl_link_up(wl); + act = true; +- if (!wl_get_drv_status(wl, DISCONNECTING, ndev)) { ++ if (wl_is_ibssmode(wl, ndev)) { ++ printk("cfg80211_ibss_joined\n"); ++ cfg80211_ibss_joined(ndev, (s8 *)&e->addr, ++ GFP_KERNEL); ++ WL_DBG(("joined in IBSS network\n")); ++ } else { ++ if (!wl_get_drv_status(wl, DISCONNECTING, ndev)) { + printk("wl_bss_connect_done succeeded with " MACDBG "\n", + MAC2STRDBG((u8*)(&e->addr))); + wl_bss_connect_done(wl, ndev, e, data, true); + WL_DBG(("joined in BSS network \"%s\"\n", + ((struct wlc_ssid *) + wl_read_prof(wl, ndev, WL_PROF_SSID))->SSID)); ++ } + } + wl_update_prof(wl, ndev, e, &act, WL_PROF_ACT); + wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID); +@@ -7261,6 +6629,7 @@ wl_notify_connect_status(struct wl_priv + reason = ntoh32(e->reason); + /* WLAN_REASON_UNSPECIFIED is used for hang up event in Android */ + reason = (reason == WLAN_REASON_UNSPECIFIED)? 0 : reason; ++ + printk("link down if %s may call cfg80211_disconnected. " + "event : %d, reason=%d from " MACDBG "\n", + ndev->name, event, ntoh32(e->reason), +@@ -7322,28 +6691,21 @@ wl_notify_connect_status(struct wl_priv + if (wl_get_drv_status(wl, CONNECTING, ndev)) + wl_bss_connect_done(wl, ndev, e, data, false); + } else { +- WL_DBG(("%s nothing\n", __FUNCTION__)); ++ printk("%s nothing\n", __FUNCTION__); + } +- } else { +- WL_ERR(("Invalid ndev status %d\n", wl_get_mode_by_netdev(wl, ndev))); + } + return err; + } + + static s32 +-wl_notify_roaming_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev, ++wl_notify_roaming_status(struct wl_priv *wl, struct net_device *ndev, + const wl_event_msg_t *e, void *data) + { + bool act; +- struct net_device *ndev = NULL; + s32 err = 0; + u32 event = be32_to_cpu(e->event_type); + u32 status = be32_to_cpu(e->status); +- + WL_DBG(("Enter \n")); +- +- ndev = cfgdev_to_wlc_ndev(cfgdev, wl); +- + if (event == WLC_E_ROAM && status == WLC_E_STATUS_SUCCESS) { + if (wl_get_drv_status(wl, CONNECTED, ndev)) + wl_bss_roaming_done(wl, ndev, e, data); +@@ -7395,8 +6757,8 @@ static s32 wl_get_assoc_ies(struct wl_pr + if (conn_info->req_ie_len <= MAX_REQ_LINE) + memcpy(conn_info->req_ie, wl->extra_buf, conn_info->req_ie_len); + else { +- WL_ERR(("IE size %d above max %d size \n", +- conn_info->req_ie_len, MAX_REQ_LINE)); ++ WL_ERR(("%s IE size %d above max %d size \n", ++ __FUNCTION__, conn_info->req_ie_len, MAX_REQ_LINE)); + return err; + } + } else { +@@ -7413,8 +6775,8 @@ static s32 wl_get_assoc_ies(struct wl_pr + if (conn_info->resp_ie_len <= MAX_REQ_LINE) + memcpy(conn_info->resp_ie, wl->extra_buf, conn_info->resp_ie_len); + else { +- WL_ERR(("IE size %d above max %d size \n", +- conn_info->resp_ie_len, MAX_REQ_LINE)); ++ WL_ERR(("%s IE size %d above max %d size \n", ++ __FUNCTION__, conn_info->resp_ie_len, MAX_REQ_LINE)); + return err; + } + } else { +@@ -7458,7 +6820,7 @@ static void wl_ch_to_chanspec(int ch, st + } + } + +-static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev) ++static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev, u8 is_roam_done) + { + struct cfg80211_bss *bss; + struct wl_bss_info *bi; +@@ -7468,12 +6830,16 @@ static s32 wl_update_bss_info(struct wl_ + s32 dtim_period; + size_t ie_len; + u8 *ie; ++ u8 *ssidie; + u8 *curbssid; + s32 err = 0; + struct wiphy *wiphy; + + wiphy = wl_to_wiphy(wl); + ++ if (wl_is_ibssmode(wl, ndev)) ++ return err; ++ + ssid = (struct wlc_ssid *)wl_read_prof(wl, ndev, WL_PROF_SSID); + curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID); + bss = cfg80211_get_bss(wiphy, NULL, curbssid, +@@ -7492,11 +6858,17 @@ static s32 wl_update_bss_info(struct wl_ + } + bi = (struct wl_bss_info *)(wl->extra_buf + 4); + if (memcmp(bi->BSSID.octet, curbssid, ETHER_ADDR_LEN)) { +- WL_ERR(("Bssid doesn't match\n")); + err = -EIO; + goto update_bss_info_out; + } +- err = wl_inform_single_bss(wl, bi); ++ ++ ie = ((u8 *)bi) + bi->ie_offset; ++ ie_len = bi->ie_length; ++ ssidie = (u8 *)cfg80211_find_ie(WLAN_EID_SSID, ie, ie_len); ++ if (ssidie && ssidie[1] == bi->SSID_len && !ssidie[2] && bi->SSID[0]) ++ memcpy(ssidie + 2, bi->SSID, bi->SSID_len); ++ ++ err = wl_inform_single_bss(wl, bi, is_roam_done); + if (unlikely(err)) + goto update_bss_info_out; + +@@ -7505,19 +6877,10 @@ static s32 wl_update_bss_info(struct wl_ + beacon_interval = cpu_to_le16(bi->beacon_period); + } else { + WL_DBG(("Found the AP in the list - BSSID %pM\n", bss->bssid)); +-#if defined(WL_CFG80211_P2P_DEV_IF) +- ie = (u8 *)bss->ies->data; +- ie_len = bss->ies->len; +-#else + ie = bss->information_elements; + ie_len = bss->len_information_elements; +-#endif /* WL_CFG80211_P2P_DEV_IF */ + beacon_interval = bss->beacon_interval; +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)) +- cfg80211_put_bss(wiphy, bss); +-#else + cfg80211_put_bss(bss); +-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */ + } + + tim = bcm_parse_tlvs(ie, ie_len, WLAN_EID_TIM); +@@ -7541,9 +6904,6 @@ static s32 wl_update_bss_info(struct wl_ + wl_update_prof(wl, ndev, NULL, &dtim_period, WL_PROF_DTIMPERIOD); + + update_bss_info_out: +- if (unlikely(err)) { +- WL_ERR(("Failed with error %d\n", err)); +- } + mutex_unlock(&wl->usr_sync); + return err; + } +@@ -7555,52 +6915,21 @@ wl_bss_roaming_done(struct wl_priv *wl, + struct wl_connect_info *conn_info = wl_to_conn(wl); + s32 err = 0; + u8 *curbssid; +-#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39) +- struct wl_bss_info *bss_info; +- struct wiphy *wiphy = wl_to_wiphy(wl); +- struct ieee80211_supported_band *band; +- struct ieee80211_channel *notify_channel = NULL; +- u8 *buf; +- u16 channel; +- u32 freq; +-#endif /* LINUX_VERSION > 2.6.39 */ + + wl_get_assoc_ies(wl, ndev); + wl_update_prof(wl, ndev, NULL, (void *)(e->addr.octet), WL_PROF_BSSID); + curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID); +- wl_update_bss_info(wl, ndev); ++ wl_update_bss_info(wl, ndev, 1); + wl_update_pmklist(ndev, wl->pmk_list, err); +- +-#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39) +- /* channel info for cfg80211_roamed introduced in 2.6.39-rc1 */ +- buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL); +- if (!buf) +- goto done; +- +- *(__le32 *)buf = htod32(WL_EXTRA_BUF_MAX); +- err = wldev_ioctl(ndev, WLC_GET_BSS_INFO, buf, WL_EXTRA_BUF_MAX, false); +- if (err) +- goto done; +- +- bss_info = (struct wl_bss_info *)(buf + 4); +- channel = bss_info->ctl_ch ? bss_info->ctl_ch : +- CHSPEC_CHANNEL(wl_chspec_driver_to_host(bss_info->chanspec)); +- if (channel <= CH_MAX_2G_CHANNEL) +- band = wiphy->bands[IEEE80211_BAND_2GHZ]; +- else +- band = wiphy->bands[IEEE80211_BAND_5GHZ]; +- freq = ieee80211_channel_to_frequency(channel, band->band); +- notify_channel = ieee80211_get_channel(wiphy, freq); +-done: +- kfree(buf); +-#endif /* LINUX_VERSION > 2.6.39 */ +- + printk("wl_bss_roaming_done succeeded to " MACDBG "\n", + MAC2STRDBG((u8*)(&e->addr))); + + cfg80211_roamed(ndev, +-#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39) +- notify_channel, ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0) ++ NULL, /* struct cfg80211_bss *bss */ ++#elif LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39) ++ NULL, + #endif + curbssid, + conn_info->req_ie, conn_info->req_ie_len, +@@ -7618,9 +6947,6 @@ wl_bss_connect_done(struct wl_priv *wl, + { + struct wl_connect_info *conn_info = wl_to_conn(wl); + struct wl_security *sec = wl_read_prof(wl, ndev, WL_PROF_SEC); +-#if defined(ROAM_ENABLE) && defined(ROAM_AP_ENV_DETECTION) +- dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); +-#endif /* ROAM_AP_ENV_DETECTION */ + s32 err = 0; + u8 *curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID); + if (!sec) { +@@ -7648,24 +6974,14 @@ wl_bss_connect_done(struct wl_priv *wl, + } + #endif /* ESCAN_RESULT_PATCH */ + if (wl_get_drv_status(wl, CONNECTING, ndev)) { +- wl_cfg80211_scan_abort(wl); + wl_clr_drv_status(wl, CONNECTING, ndev); + if (completed) { + wl_get_assoc_ies(wl, ndev); + wl_update_prof(wl, ndev, NULL, (void *)(e->addr.octet), WL_PROF_BSSID); + curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID); +- wl_update_bss_info(wl, ndev); ++ wl_update_bss_info(wl, ndev, 0); + wl_update_pmklist(ndev, wl->pmk_list, err); + wl_set_drv_status(wl, CONNECTED, ndev); +-#if defined(ROAM_ENABLE) && defined(ROAM_AP_ENV_DETECTION) +- if (dhd->roam_env_detection) +- wldev_iovar_setint(ndev, "roam_env_detection", +- AP_ENV_INDETERMINATE); +-#endif /* ROAM_AP_ENV_DETECTION */ +- if (ndev != wl_to_prmry_ndev(wl)) { +- /* reinitialize completion to clear previous count */ +- INIT_COMPLETION(wl->iface_disable); +- } + } + cfg80211_connect_result(ndev, + curbssid, +@@ -7687,15 +7003,12 @@ wl_bss_connect_done(struct wl_priv *wl, + } + + static s32 +-wl_notify_mic_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev, ++wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev, + const wl_event_msg_t *e, void *data) + { +- struct net_device *ndev = NULL; + u16 flags = ntoh16(e->flags); + enum nl80211_key_type key_type; + +- ndev = cfgdev_to_wlc_ndev(cfgdev, wl); +- + mutex_lock(&wl->usr_sync); + if (flags & WLC_EVENT_MSG_GROUP) + key_type = NL80211_KEYTYPE_GROUP; +@@ -7711,15 +7024,11 @@ wl_notify_mic_status(struct wl_priv *wl, + + #ifdef PNO_SUPPORT + static s32 +-wl_notify_pfn_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev, ++wl_notify_pfn_status(struct wl_priv *wl, struct net_device *ndev, + const wl_event_msg_t *e, void *data) + { +- struct net_device *ndev = NULL; +- + WL_ERR((">>> PNO Event\n")); + +- ndev = cfgdev_to_wlc_ndev(cfgdev, wl); +- + #ifndef WL_SCHED_SCAN + mutex_lock(&wl->usr_sync); + /* TODO: Use cfg80211_sched_scan_results(wiphy); */ +@@ -7736,12 +7045,11 @@ wl_notify_pfn_status(struct wl_priv *wl, + #endif /* PNO_SUPPORT */ + + static s32 +-wl_notify_scan_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev, ++wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev, + const wl_event_msg_t *e, void *data) + { + struct channel_info channel_inform; + struct wl_scan_results *bss_list; +- struct net_device *ndev = NULL; + u32 len = WL_SCAN_BUF_MAX; + s32 err = 0; + unsigned long flags; +@@ -7754,8 +7062,6 @@ wl_notify_scan_status(struct wl_priv *wl + if (wl->iscan_on && wl->iscan_kickstart) + return wl_wakeup_iscan(wl_to_iscan(wl)); + +- ndev = cfgdev_to_wlc_ndev(cfgdev, wl); +- + mutex_lock(&wl->usr_sync); + wl_clr_drv_status(wl, SCANNING, ndev); + err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &channel_inform, +@@ -7798,7 +7104,6 @@ scan_done_out: + mutex_unlock(&wl->usr_sync); + return err; + } +- + static s32 + wl_frame_get_mgmt(u16 fc, const struct ether_addr *da, + const struct ether_addr *sa, const struct ether_addr *bssid, +@@ -7844,39 +7149,33 @@ wl_frame_get_mgmt(u16 fc, const struct e + + + void +-wl_stop_wait_next_action_frame(struct wl_priv *wl) ++wl_stop_wait_next_action_frame(struct wl_priv *wl, struct net_device *ndev) + { +- if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) { +- if (!(wl_get_p2p_status(wl, ACTION_TX_COMPLETED) || +- wl_get_p2p_status(wl, ACTION_TX_NOACK))) +- wl_set_p2p_status(wl, ACTION_TX_COMPLETED); +- ++ if (wl_get_drv_status_all(wl, SENDING_ACT_FRM) && ++ (wl_get_p2p_status(wl, ACTION_TX_COMPLETED) || ++ wl_get_p2p_status(wl, ACTION_TX_NOACK))) { + WL_DBG(("*** Wake UP ** abort actframe iovar\n")); + /* if channel is not zero, "actfame" uses off channel scan. + * So abort scan for off channel completion. + */ + if (wl->af_sent_channel) +- wl_cfg80211_scan_abort(wl); ++ /* wl_cfg80211_scan_abort(wl, ndev); */ ++ wl_notify_escan_complete(wl, ++ (ndev == wl->p2p_net) ? wl_to_prmry_ndev(wl) : ndev, true, true); + } + #ifdef WL_CFG80211_SYNC_GON + else if (wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM_LISTEN)) { + WL_DBG(("*** Wake UP ** abort listen for next af frame\n")); + /* So abort scan to cancel listen */ +- wl_cfg80211_scan_abort(wl); ++ wl_notify_escan_complete(wl, ++ (ndev == wl->p2p_net) ? wl_to_prmry_ndev(wl) : ndev, true, true); + } + #endif /* WL_CFG80211_SYNC_GON */ + } + +- +-int wl_cfg80211_get_ioctl_version(void) +-{ +- return ioctl_version; +-} +- + static s32 +-wl_notify_rx_mgmt_frame(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev, ++wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev, + const wl_event_msg_t *e, void *data) +- + { + struct ieee80211_supported_band *band; + struct wiphy *wiphy = wl_to_wiphy(wl); +@@ -7885,7 +7184,7 @@ wl_notify_rx_mgmt_frame(struct wl_priv * + bool isfree = false; + s32 err = 0; + s32 freq; +- struct net_device *ndev = NULL; ++ struct net_device *dev = NULL; + wifi_p2p_pub_act_frame_t *act_frm = NULL; + wifi_p2p_action_frame_t *p2p_act_frm = NULL; + wifi_p2psd_gas_pub_act_frame_t *sd_act_frm = NULL; +@@ -7899,7 +7198,11 @@ wl_notify_rx_mgmt_frame(struct wl_priv * + + memset(&bssid, 0, ETHER_ADDR_LEN); + +- ndev = cfgdev_to_wlc_ndev(cfgdev, wl); ++ if (wl->p2p_net == ndev) { ++ dev = wl_to_prmry_ndev(wl); ++ } else { ++ dev = ndev; ++ } + + if (channel <= CH_MAX_2G_CHANNEL) + band = wiphy->bands[IEEE80211_BAND_2GHZ]; +@@ -7909,17 +7212,17 @@ wl_notify_rx_mgmt_frame(struct wl_priv * + WL_ERR(("No valid band")); + return -EINVAL; + } +-#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) ++#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS) + freq = ieee80211_channel_to_frequency(channel); + (void)band->band; + #else + freq = ieee80211_channel_to_frequency(channel, band->band); + #endif + if (event == WLC_E_ACTION_FRAME_RX) { +- wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr", ++ wldev_iovar_getbuf_bsscfg(dev, "cur_etheraddr", + NULL, 0, wl->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &wl->ioctl_buf_sync); + +- err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false); ++ err = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false); + if (err < 0) + WL_ERR(("WLC_GET_BSSID error %d\n", err)); + memcpy(da.octet, wl->ioctl_buf, ETHER_ADDR_LEN); +@@ -7927,8 +7230,8 @@ wl_notify_rx_mgmt_frame(struct wl_priv * + &mgmt_frame, &mgmt_frame_len, + (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1)); + if (err < 0) { +- WL_ERR(("Error in receiving action frame len %d channel %d freq %d\n", +- mgmt_frame_len, channel, freq)); ++ WL_ERR(("%s: Error in receiving action frame len %d channel %d freq %d\n", ++ __func__, mgmt_frame_len, channel, freq)); + goto exit; + } + isfree = true; +@@ -7943,44 +7246,28 @@ wl_notify_rx_mgmt_frame(struct wl_priv * + (void) p2p_act_frm; + } else if (wl_cfgp2p_is_gas_action(&mgmt_frame[DOT11_MGMT_HDR_LEN], + mgmt_frame_len - DOT11_MGMT_HDR_LEN)) { +- + sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *) + (&mgmt_frame[DOT11_MGMT_HDR_LEN]); + if (sd_act_frm && wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM)) { + if (wl->next_af_subtype == sd_act_frm->action) { + WL_DBG(("We got a right next frame of SD!(%d)\n", + sd_act_frm->action)); +- wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM, ndev); ++ wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM, ++ (ndev == wl->p2p_net) ? ++ wl_to_prmry_ndev(wl) : ndev); + + /* Stop waiting for next AF. */ +- wl_stop_wait_next_action_frame(wl); ++ wl_stop_wait_next_action_frame(wl, ndev); + } + } + (void) sd_act_frm; + } else { + /* +- * if we got normal action frame and ndev is p2p0, +- * we have to change ndev from p2p0 to wlan0 ++ * if we got normal action frame and ndev is p2p0, ++ * we have to change ndev from p2p0 to wlan0 + */ +-#if defined(WL_ENABLE_P2P_IF) +- if (wl->p2p_net == cfgdev) +- cfgdev = wl_to_prmry_ndev(wl); +-#endif /* WL_ENABLE_P2P_IF */ +- +- if (wl->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) { +- u8 action = 0; +- if (wl_get_public_action(&mgmt_frame[DOT11_MGMT_HDR_LEN], +- mgmt_frame_len - DOT11_MGMT_HDR_LEN, &action) != BCME_OK) { +- WL_DBG(("Recived action is not public action frame\n")); +- } else if (wl->next_af_subtype == action) { +- WL_DBG(("Recived action is the waiting action(%d)\n", +- action)); +- wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM, ndev); +- +- /* Stop waiting for next AF. */ +- wl_stop_wait_next_action_frame(wl); +- } +- } ++ if (wl->p2p_net == ndev) ++ ndev = wl_to_prmry_ndev(wl); + } + + if (act_frm) { +@@ -7989,22 +7276,24 @@ wl_notify_rx_mgmt_frame(struct wl_priv * + if (wl->next_af_subtype == act_frm->subtype) { + WL_DBG(("We got a right next frame!(%d)\n", + act_frm->subtype)); +- wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM, ndev); ++ wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM, ++ (ndev == wl->p2p_net) ? ++ wl_to_prmry_ndev(wl) : ndev); + + /* Stop waiting for next AF. */ +- wl_stop_wait_next_action_frame(wl); ++ wl_stop_wait_next_action_frame(wl, ndev); + } + } + } + + wl_cfgp2p_print_actframe(false, &mgmt_frame[DOT11_MGMT_HDR_LEN], +- mgmt_frame_len - DOT11_MGMT_HDR_LEN, channel); ++ mgmt_frame_len - DOT11_MGMT_HDR_LEN); + /* + * After complete GO Negotiation, roll back to mpc mode + */ + if (act_frm && ((act_frm->subtype == P2P_PAF_GON_CONF) || + (act_frm->subtype == P2P_PAF_PROVDIS_RSP))) { +- wldev_iovar_setint(ndev, "mpc", 1); ++ wldev_iovar_setint(dev, "mpc", 1); + } + if (act_frm && (act_frm->subtype == P2P_PAF_GON_CONF)) { + WL_DBG(("P2P: GO_NEG_PHASE status cleared \n")); +@@ -8036,12 +7325,12 @@ wl_notify_rx_mgmt_frame(struct wl_priv * + } + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) +- cfg80211_rx_mgmt(cfgdev, freq, 0, mgmt_frame, mgmt_frame_len, GFP_ATOMIC); ++ cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, mgmt_frame_len, GFP_ATOMIC); + #else +- cfg80211_rx_mgmt(cfgdev, freq, mgmt_frame, mgmt_frame_len, GFP_ATOMIC); ++ cfg80211_rx_mgmt(ndev, freq, mgmt_frame, mgmt_frame_len, GFP_ATOMIC); + #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) */ + +- WL_DBG(("mgmt_frame_len (%d) , e->datalen (%d), channel (%d), freq (%d)\n", ++ WL_DBG(("%s: mgmt_frame_len (%d) , e->datalen (%d), channel (%d), freq (%d)\n", __func__, + mgmt_frame_len, ntoh32(e->datalen), channel, freq)); + exit: + if (isfree) +@@ -8059,15 +7348,14 @@ wl_notify_sched_scan_results(struct wl_p + const wl_event_msg_t *e, void *data) + { + wl_pfn_net_info_t *netinfo, *pnetinfo; ++ struct cfg80211_scan_request request; + struct wiphy *wiphy = wl_to_wiphy(wl); + int err = 0; +- struct cfg80211_scan_request *request = NULL; + struct cfg80211_ssid ssid[MAX_PFN_LIST_COUNT]; + struct ieee80211_channel *channel = NULL; + int channel_req = 0; + int band = 0; + struct wl_pfn_scanresults *pfn_result = (struct wl_pfn_scanresults *)data; +- int n_pfn_results = pfn_result->count; + + WL_DBG(("Enter\n")); + +@@ -8075,32 +7363,26 @@ wl_notify_sched_scan_results(struct wl_p + WL_PNO(("PFN NET LOST event. Do Nothing \n")); + return 0; + } +- WL_PNO((">>> PFN NET FOUND event. count:%d \n", n_pfn_results)); +- if (n_pfn_results > 0) { ++ WL_PNO((">>> PFN NET FOUND event. count:%d \n", pfn_result->count)); ++ if (pfn_result->count > 0) { + int i; + +- if (n_pfn_results > MAX_PFN_LIST_COUNT) +- n_pfn_results = MAX_PFN_LIST_COUNT; +- pnetinfo = (wl_pfn_net_info_t *)(data + sizeof(wl_pfn_scanresults_t) +- - sizeof(wl_pfn_net_info_t)); +- ++ memset(&request, 0x00, sizeof(struct cfg80211_scan_request)); + memset(&ssid, 0x00, sizeof(ssid)); ++ request.wiphy = wiphy; + +- request = kzalloc(sizeof(*request) +- + sizeof(*request->channels) * n_pfn_results, +- GFP_KERNEL); ++ pnetinfo = (wl_pfn_net_info_t *)(data + sizeof(wl_pfn_scanresults_t) ++ - sizeof(wl_pfn_net_info_t)); + channel = (struct ieee80211_channel *)kzalloc( +- (sizeof(struct ieee80211_channel) * n_pfn_results), ++ (sizeof(struct ieee80211_channel) * MAX_PFN_LIST_COUNT), + GFP_KERNEL); +- if (!request || !channel) { ++ if (!channel) { + WL_ERR(("No memory")); + err = -ENOMEM; + goto out_err; + } + +- request->wiphy = wiphy; +- +- for (i = 0; i < n_pfn_results; i++) { ++ for (i = 0; i < pfn_result->count; i++) { + netinfo = &pnetinfo[i]; + if (!netinfo) { + WL_ERR(("Invalid netinfo ptr. index:%d", i)); +@@ -8118,7 +7400,7 @@ wl_notify_sched_scan_results(struct wl_p + memcpy(ssid[i].ssid, netinfo->pfnsubnet.SSID, + netinfo->pfnsubnet.SSID_len); + ssid[i].ssid_len = netinfo->pfnsubnet.SSID_len; +- request->n_ssids++; ++ request.n_ssids++; + + channel_req = netinfo->pfnsubnet.channel; + band = (channel_req <= CH_MAX_2G_CHANNEL) ? NL80211_BAND_2GHZ +@@ -8126,13 +7408,13 @@ wl_notify_sched_scan_results(struct wl_p + channel[i].center_freq = ieee80211_channel_to_frequency(channel_req, band); + channel[i].band = band; + channel[i].flags |= IEEE80211_CHAN_NO_HT40; +- request->channels[i] = &channel[i]; +- request->n_channels++; ++ request.channels[i] = &channel[i]; ++ request.n_channels++; + } + + /* assign parsed ssid array */ +- if (request->n_ssids) +- request->ssids = &ssid[0]; ++ if (request.n_ssids) ++ request.ssids = &ssid[0]; + + if (wl_get_drv_status_all(wl, SCANNING)) { + /* Abort any on-going scan */ +@@ -8146,7 +7428,6 @@ wl_notify_sched_scan_results(struct wl_p + wl_clr_drv_status(wl, SCANNING, ndev); + goto out_err; + } +- p2p_scan(wl) = false; + } + + wl_set_drv_status(wl, SCANNING, ndev); +@@ -8155,7 +7436,7 @@ wl_notify_sched_scan_results(struct wl_p + err = wl_do_escan(wl, wiphy, ndev, NULL); + #else + WL_PNO((">>> Doing targeted ESCAN on PNO event\n")); +- err = wl_do_escan(wl, wiphy, ndev, request); ++ err = wl_do_escan(wl, wiphy, ndev, &request); + #endif + if (err) { + wl_clr_drv_status(wl, SCANNING, ndev); +@@ -8167,8 +7448,6 @@ wl_notify_sched_scan_results(struct wl_p + WL_ERR(("FALSE PNO Event. (pfn_count == 0) \n")); + } + out_err: +- if (request) +- kfree(request); + if (channel) + kfree(channel); + return err; +@@ -8217,32 +7496,11 @@ static void wl_init_event_handler(struct + wl->evt_handler[WLC_E_P2P_DISC_LISTEN_COMPLETE] = wl_cfgp2p_listen_complete; + wl->evt_handler[WLC_E_ACTION_FRAME_COMPLETE] = wl_cfgp2p_action_tx_complete; + wl->evt_handler[WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE] = wl_cfgp2p_action_tx_complete; +- wl->evt_handler[WLC_E_JOIN] = wl_notify_connect_status; +- wl->evt_handler[WLC_E_START] = wl_notify_connect_status; + #ifdef PNO_SUPPORT + wl->evt_handler[WLC_E_PFN_NET_FOUND] = wl_notify_pfn_status; + #endif /* PNO_SUPPORT */ +-#ifdef WLTDLS +- wl->evt_handler[WLC_E_TDLS_PEER_EVENT] = wl_tdls_event_handler; +-#endif /* WLTDLS */ + } + +-#if defined(STATIC_WL_PRIV_STRUCT) +-static void +-wl_init_escan_result_buf(struct wl_priv *wl) +-{ +- wl->escan_info.escan_buf = dhd_os_prealloc(NULL, DHD_PREALLOC_WIPHY_ESCAN0, 0); +- bzero(wl->escan_info.escan_buf, ESCAN_BUF_SIZE); +-} +- +-static void +-wl_deinit_escan_result_buf(struct wl_priv *wl) +-{ +- wl->escan_info.escan_buf = NULL; +- +-} +-#endif /* STATIC_WL_PRIV_STRUCT */ +- + static s32 wl_init_priv_mem(struct wl_priv *wl) + { + WL_DBG(("Enter \n")); +@@ -8304,7 +7562,8 @@ static s32 wl_init_priv_mem(struct wl_pr + WL_ERR(("wl->ie alloc failed\n")); + goto init_priv_mem_out; + } +- wl_init_escan_result_buf(wl); ++ wl->escan_info.escan_buf = dhd_os_prealloc(NULL, DHD_PREALLOC_WIPHY_ESCAN0, 0); ++ bzero(wl->escan_info.escan_buf, ESCAN_BUF_SIZE); + #endif /* STATIC_WL_PRIV_STRUCT */ + wl->afx_hdl = (void *)kzalloc(sizeof(*wl->afx_hdl), GFP_KERNEL); + if (unlikely(!wl->afx_hdl)) { +@@ -8349,7 +7608,7 @@ static void wl_deinit_priv_mem(struct wl + wl->conn_info = NULL; + kfree(wl->ie); + wl->ie = NULL; +- wl_deinit_escan_result_buf(wl); ++ wl->escan_info.escan_buf = NULL; + #endif /* STATIC_WL_PRIV_STRUCT */ + if (wl->afx_hdl) { + cancel_work_sync(&wl->afx_hdl->work); +@@ -8374,7 +7633,11 @@ static s32 wl_create_event_handler(struc + /* Do not use DHD in cfg driver */ + wl->event_tsk.thr_pid = -1; + +- PROC_START(wl_event_handler, wl, &wl->event_tsk, 0, "wl_event_handler"); ++#ifdef USE_KTHREAD_API ++ PROC_START2(wl_event_handler, wl, &wl->event_tsk, 0, "wl_event_handler"); ++#else ++ PROC_START(wl_event_handler, wl, &wl->event_tsk, 0); ++#endif + if (wl->event_tsk.thr_pid < 0) + ret = -ENOMEM; + return ret; +@@ -8506,7 +7769,7 @@ static s32 wl_iscan_inprogress(struct wl + wl_run_iscan(iscan, NULL, WL_SCAN_ACTION_CONTINUE); + mutex_unlock(&wl->usr_sync); + /* Reschedule the timer */ +- mod_timer(&iscan->timer, jiffies + msecs_to_jiffies(iscan->timer_ms)); ++ mod_timer(&iscan->timer, jiffies + msecs_to_jiffies(iscan->timer_ms)); + iscan->timer_on = 1; + + return err; +@@ -8554,7 +7817,7 @@ static s32 wl_iscan_thread(void *data) + del_timer_sync(&iscan->timer); + iscan->timer_on = 0; + } +- WL_DBG(("was terminated\n")); ++ WL_DBG(("%s was terminated\n", __func__)); + + return 0; + } +@@ -8569,19 +7832,17 @@ static void wl_scan_timeout(unsigned lon + return; + } + bzero(&msg, sizeof(wl_event_msg_t)); +- WL_ERR(("timer expired\n")); ++ WL_ERR(("timer expired\n")); + if (wl->escan_on) { + msg.event_type = hton32(WLC_E_ESCAN_RESULT); + msg.status = hton32(WLC_E_STATUS_TIMEOUT); + msg.reason = 0xFFFFFFFF; + wl_cfg80211_event(wl_to_prmry_ndev(wl), &msg, NULL); + } else { +- /* Need to check it try to access SDIO */ + WL_ERR(("SCAN Timeout(ISCAN)\n")); +- wl_notify_iscan_complete(wl_to_iscan(wl), true); ++ wl_notify_iscan_complete(wl_to_iscan(wl), true); + } + } +- + static void wl_iscan_timer(unsigned long data) + { + struct wl_iscan_ctrl *iscan = (struct wl_iscan_ctrl *)data; +@@ -8637,37 +7898,16 @@ wl_cfg80211_netdev_notifier_call(struct + return NOTIFY_DONE; + switch (state) { + case NETDEV_DOWN: +- { +- int max_wait_timeout = 2; +- int max_wait_count = 100; +- unsigned long limit = jiffies + max_wait_timeout * HZ; +- while (work_pending(&wdev->cleanup_work)) { +- if (refcnt%5 == 0) { +- WL_ERR(("[NETDEV_DOWN] wait for " +- "complete of cleanup_work" +- " (%d th)\n", refcnt)); +- } +- if (!time_before(jiffies, limit)) { +- WL_ERR(("[NETDEV_DOWN] cleanup_work" +- " of CFG80211 is not" +- " completed in %d sec\n", +- max_wait_timeout)); +- break; +- } +- if (refcnt >= max_wait_count) { +- WL_ERR(("[NETDEV_DOWN] cleanup_work" +- " of CFG80211 is not" +- " completed in %d loop\n", +- max_wait_count)); +- break; +- } ++ while (work_pending(&wdev->cleanup_work) && refcnt < 100) { ++ if (refcnt%5 == 0) ++ WL_ERR(("%s : [NETDEV_DOWN] work_pending (%d th)\n", ++ __FUNCTION__, refcnt)); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(100); + set_current_state(TASK_RUNNING); + refcnt++; + } + break; +- } + + case NETDEV_UNREGISTER: + /* after calling list_del_rcu(&wdev->list) */ +@@ -8693,72 +7933,55 @@ static struct notifier_block wl_cfg80211 + .notifier_call = wl_cfg80211_netdev_notifier_call, + }; + +-static void wl_cfg80211_scan_abort(struct wl_priv *wl) +-{ +- wl_scan_params_t *params = NULL; +- s32 params_size = 0; +- s32 err = BCME_OK; +- struct net_device *dev = wl_to_prmry_ndev(wl); +- if (!in_atomic()) { +- /* Our scan params only need space for 1 channel and 0 ssids */ +- params = wl_cfg80211_scan_alloc_params(-1, 0, ¶ms_size); +- if (params == NULL) { +- WL_ERR(("scan params allocation failed \n")); +- err = -ENOMEM; +- } else { +- /* Do a scan abort to stop the driver's scan engine */ +- err = wldev_ioctl(dev, WLC_SCAN, params, params_size, true); +- if (err < 0) { +- WL_ERR(("scan abort failed \n")); +- } +- kfree(params); +- } +- } +-} +- + static s32 wl_notify_escan_complete(struct wl_priv *wl, + struct net_device *ndev, + bool aborted, bool fw_abort) + { ++ wl_scan_params_t *params = NULL; ++ s32 params_size = 0; + s32 err = BCME_OK; + unsigned long flags; + struct net_device *dev; + + WL_DBG(("Enter \n")); +- if (!ndev) { +- WL_ERR(("ndev is null\n")); +- err = BCME_ERROR; +- return err; +- } + +- if (wl->escan_info.ndev != ndev) { ++ if (wl->escan_info.ndev != ndev) ++ { + WL_ERR(("ndev is different %p %p\n", wl->escan_info.ndev, ndev)); +- err = BCME_ERROR; + return err; + } + + if (wl->scan_request) { +- dev = wl_to_prmry_ndev(wl); +-#if defined(WL_ENABLE_P2P_IF) +- if (wl->scan_request->dev != wl->p2p_net) ++ if (wl->scan_request->dev == wl->p2p_net) ++ dev = wl_to_prmry_ndev(wl); ++ else + dev = wl->scan_request->dev; +-#endif /* WL_ENABLE_P2P_IF */ + } + else { + WL_DBG(("wl->scan_request is NULL may be internal scan." +- "doing scan_abort for ndev %p primary %p", +- ndev, wl_to_prmry_ndev(wl))); ++ "doing scan_abort for ndev %p primary %p p2p_net %p", ++ ndev, wl_to_prmry_ndev(wl), wl->p2p_net)); + dev = ndev; + } + if (fw_abort && !in_atomic()) { +- wl_cfg80211_scan_abort(wl); ++ /* Our scan params only need space for 1 channel and 0 ssids */ ++ params = wl_cfg80211_scan_alloc_params(-1, 0, ¶ms_size); ++ if (params == NULL) { ++ WL_ERR(("scan params allocation failed \n")); ++ err = -ENOMEM; ++ } else { ++ /* Do a scan abort to stop the driver's scan engine */ ++ err = wldev_ioctl(dev, WLC_SCAN, params, params_size, true); ++ if (err < 0) { ++ WL_ERR(("scan abort failed \n")); ++ } ++ } + } +- + if (timer_pending(&wl->scan_timeout)) + del_timer_sync(&wl->scan_timeout); + #if defined(ESCAN_RESULT_PATCH) + if (likely(wl->scan_request)) { +- wl->bss_list = wl_escan_get_buf(wl, aborted); ++ wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf; + wl_inform_bss(wl); + } + #endif /* ESCAN_RESULT_PATCH */ +@@ -8766,7 +7989,9 @@ static s32 wl_notify_escan_complete(stru + #ifdef WL_SCHED_SCAN + if (wl->sched_scan_req && !wl->scan_request) { + WL_PNO((">>> REPORTING SCHED SCAN RESULTS \n")); +- if (!aborted) ++ if (aborted) ++ cfg80211_sched_scan_stopped(wl->sched_scan_req->wiphy); ++ else + cfg80211_sched_scan_results(wl->sched_scan_req->wiphy); + wl->sched_scan_running = FALSE; + wl->sched_scan_req = NULL; +@@ -8780,10 +8005,14 @@ static s32 wl_notify_escan_complete(stru + wl_clr_p2p_status(wl, SCANNING); + wl_clr_drv_status(wl, SCANNING, dev); + spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); ++ if (params) ++ kfree(params); ++ + return err; + } + +-static s32 wl_escan_handler(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev, ++static s32 wl_escan_handler(struct wl_priv *wl, ++ struct net_device *ndev, + const wl_event_msg_t *e, void *data) + { + s32 err = BCME_OK; +@@ -8793,7 +8022,6 @@ static s32 wl_escan_handler(struct wl_pr + wl_bss_info_t *bss = NULL; + wl_scan_results_t *list; + wifi_p2p_ie_t * p2p_ie; +- struct net_device *ndev = NULL; + u32 bi_length; + u32 i; + u8 *p2p_dev_addr = NULL; +@@ -8801,8 +8029,6 @@ static s32 wl_escan_handler(struct wl_pr + WL_DBG((" enter event type : %d, status : %d \n", + ntoh32(e->event_type), ntoh32(e->status))); + +- ndev = cfgdev_to_wlc_ndev(cfgdev, wl); +- + mutex_lock(&wl->usr_sync); + /* P2P SCAN is coming from primary interface */ + if (wl_get_p2p_status(wl, SCANNING)) { +@@ -8815,16 +8041,13 @@ static s32 wl_escan_handler(struct wl_pr + if (!ndev || !wl->escan_on || + (!wl_get_drv_status(wl, SCANNING, ndev) && + !wl->sched_scan_running)) { +- WL_ERR(("escan is not ready ndev %p wl->escan_on %d" +- " drv_status 0x%x e_type %d e_states %d\n", +- ndev, wl->escan_on, wl_get_drv_status(wl, SCANNING, ndev), +- ntoh32(e->event_type), ntoh32(e->status))); ++ WL_ERR(("escan is not ready ndev %p wl->escan_on %d drv_status 0x%x\n", ++ ndev, wl->escan_on, wl_get_drv_status(wl, SCANNING, ndev))); + goto exit; + } +- escan_result = (wl_escan_result_t *)data; +- + if (status == WLC_E_STATUS_PARTIAL) { + WL_INFO(("WLC_E_STATUS_PARTIAL \n")); ++ escan_result = (wl_escan_result_t *) data; + if (!escan_result) { + WL_ERR(("Invalid escan result (NULL pointer)\n")); + goto exit; +@@ -8843,9 +8066,6 @@ static s32 wl_escan_handler(struct wl_pr + WL_ERR(("Invalid bss_info length %d: ignoring\n", bi_length)); + goto exit; + } +- if (wl_escan_check_sync_id(status, escan_result->sync_id, +- wl->escan_info.cur_sync_id) < 0) +- goto exit; + + if (!(wl_to_wiphy(wl)->interface_modes & BIT(NL80211_IFTYPE_ADHOC))) { + if (dtoh16(bi->capability) & DOT11_CAP_IBSS) { +@@ -8858,17 +8078,10 @@ static s32 wl_escan_handler(struct wl_pr + p2p_dev_addr = wl_cfgp2p_retreive_p2p_dev_addr(bi, bi_length); + if (p2p_dev_addr && !memcmp(p2p_dev_addr, + wl->afx_hdl->tx_dst_addr.octet, ETHER_ADDR_LEN)) { +- s32 channel = wf_chspec_ctlchan( ++ s32 channel = CHSPEC_CHANNEL( + wl_chspec_driver_to_host(bi->chanspec)); +- +- if ((channel > MAXCHANNEL) || (channel <= 0)) +- channel = WL_INVALID; +- else +- WL_ERR(("ACTION FRAME SCAN : Peer " MACDBG " found," +- " channel : %d\n", +- MAC2STRDBG(wl->afx_hdl->tx_dst_addr.octet), +- channel)); +- ++ WL_DBG(("ACTION FRAME SCAN : Peer " MACDBG " found, channel : %d\n", ++ MAC2STRDBG(wl->afx_hdl->tx_dst_addr.octet), channel)); + wl_clr_p2p_status(wl, SCANNING); + wl->afx_hdl->peer_chan = channel; + complete(&wl->act_frm_scan); +@@ -8877,11 +8090,20 @@ static s32 wl_escan_handler(struct wl_pr + + } else { + int cur_len = WL_SCAN_RESULTS_FIXED_SIZE; +- list = wl_escan_get_buf(wl, FALSE); +- if (scan_req_match(wl)) { ++ list = (wl_scan_results_t *)wl->escan_info.escan_buf; ++#if defined(WLP2P) && defined(WL_ENABLE_P2P_IF) ++ if (wl->p2p_net && wl->scan_request && ++ wl->scan_request->dev == wl->p2p_net) ++#else ++ if (p2p_is_on(wl) && p2p_scan(wl)) ++#endif ++ { ++#ifdef WL_HOST_BAND_MGMT ++ s32 channel = 0; ++ s32 channel_band = 0; ++#endif /* WL_HOST_BAND_MGMT */ + /* p2p scan && allow only probe response */ +- if ((wl->p2p->search_state != WL_P2P_DISC_ST_SCAN) && +- (bi->flags & WL_BSS_FLAGS_FROM_BEACON)) ++ if (bi->flags & WL_BSS_FLAGS_FROM_BEACON) + goto exit; + if ((p2p_ie = wl_cfgp2p_find_p2pie(((u8 *) bi) + bi->ie_offset, + bi->ie_length)) == NULL) { +@@ -8889,6 +8111,20 @@ static s32 wl_escan_handler(struct wl_pr + " response/beacon\n")); + goto exit; + } ++#ifdef WL_HOST_BAND_MGMT ++ channel = CHSPEC_CHANNEL(wl_chspec_driver_to_host(bi->chanspec)); ++ channel_band = (channel > CH_MAX_2G_CHANNEL) ? ++ WLC_BAND_5G : WLC_BAND_2G; ++ ++ ++ if ((wl->curr_band == WLC_BAND_5G) && ++ (channel_band == WLC_BAND_2G)) { ++ /* Avoid sending the GO results in band conflict */ ++ if (wl_cfgp2p_retreive_p2pattrib(p2p_ie, ++ P2P_SEID_GROUP_ID) != NULL) ++ goto exit; ++ } ++#endif /* WL_HOST_BAND_MGMT */ + } + for (i = 0; i < list->count; i++) { + bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length)) +@@ -8974,20 +8210,19 @@ static s32 wl_escan_handler(struct wl_pr + WL_ERR(("Buffer is too small: ignoring\n")); + goto exit; + } +- +- memcpy(&(((char *)list)[list->buflen]), bi, bi_length); ++ if (strlen(bi->SSID) == 0) { // terence: fix for hidden SSID ++ WL_SCAN(("Skip hidden SSID %pM\n", &bi->BSSID)); ++ goto exit; ++ } ++ memcpy(&(wl->escan_info.escan_buf[list->buflen]), bi, bi_length); + list->version = dtoh32(bi->version); + list->buflen += bi_length; + list->count++; +- + } + + } + else if (status == WLC_E_STATUS_SUCCESS) { + wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE; +- wl_escan_print_sync_id(status, wl->escan_info.cur_sync_id, +- escan_result->sync_id); +- + if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) { + WL_INFO(("ACTION FRAME SCAN DONE\n")); + wl_clr_p2p_status(wl, SCANNING); +@@ -8996,20 +8231,13 @@ static s32 wl_escan_handler(struct wl_pr + complete(&wl->act_frm_scan); + } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) { + WL_INFO(("ESCAN COMPLETED\n")); +- wl->bss_list = wl_escan_get_buf(wl, FALSE); +- if (!scan_req_match(wl)) { +- WL_TRACE_HW4(("SCAN COMPLETED: scanned AP count=%d\n", +- wl->bss_list->count)); +- } ++ wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf; + wl_inform_bss(wl); + wl_notify_escan_complete(wl, ndev, false, false); + } +- wl_escan_increment_sync_id(wl, SCAN_BUF_NEXT); + } + else if (status == WLC_E_STATUS_ABORT) { + wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE; +- wl_escan_print_sync_id(status, escan_result->sync_id, +- wl->escan_info.cur_sync_id); + if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) { + WL_INFO(("ACTION FRAME SCAN DONE\n")); + wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev); +@@ -9018,16 +8246,14 @@ static s32 wl_escan_handler(struct wl_pr + complete(&wl->act_frm_scan); + } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) { + WL_INFO(("ESCAN ABORTED\n")); +- wl->bss_list = wl_escan_get_buf(wl, TRUE); +- if (!scan_req_match(wl)) { +- WL_TRACE_HW4(("SCAN ABORTED: scanned AP count=%d\n", +- wl->bss_list->count)); +- } ++ wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf; + wl_inform_bss(wl); + wl_notify_escan_complete(wl, ndev, true, false); + } +- wl_escan_increment_sync_id(wl, SCAN_BUF_CNT); +- } else if (status == WLC_E_STATUS_NEWSCAN) { ++ } ++ else if (status == WLC_E_STATUS_NEWSCAN) ++ { ++ escan_result = (wl_escan_result_t *) data; + WL_ERR(("WLC_E_STATUS_NEWSCAN : scan_request[%p]\n", wl->scan_request)); + WL_ERR(("sync_id[%d], bss_count[%d]\n", escan_result->sync_id, + escan_result->bss_count)); +@@ -9040,8 +8266,6 @@ static s32 wl_escan_handler(struct wl_pr + } else { + WL_ERR(("unexpected Escan Event %d : abort\n", status)); + wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE; +- wl_escan_print_sync_id(status, escan_result->sync_id, +- wl->escan_info.cur_sync_id); + if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) { + WL_INFO(("ACTION FRAME SCAN DONE\n")); + wl_clr_p2p_status(wl, SCANNING); +@@ -9049,22 +8273,15 @@ static s32 wl_escan_handler(struct wl_pr + if (wl->afx_hdl->peer_chan == WL_INVALID) + complete(&wl->act_frm_scan); + } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) { +- wl->bss_list = wl_escan_get_buf(wl, TRUE); +- if (!scan_req_match(wl)) { +- WL_TRACE_HW4(("SCAN ABORTED(UNEXPECTED): " +- "scanned AP count=%d\n", +- wl->bss_list->count)); +- } ++ wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf; + wl_inform_bss(wl); + wl_notify_escan_complete(wl, ndev, true, false); + } +- wl_escan_increment_sync_id(wl, 2); + } + exit: + mutex_unlock(&wl->usr_sync); + return err; + } +- + static void wl_cfg80211_concurrent_roam(struct wl_priv *wl, int enable) + { + u32 connected_cnt = wl_get_drv_status_all(wl, CONNECTED); +@@ -9107,9 +8324,9 @@ static void wl_cfg80211_concurrent_roam( + static void wl_cfg80211_determine_vsdb_mode(struct wl_priv *wl) + { + struct net_info *iter, *next; +- u32 ctl_chan = 0; ++ u32 chan = 0; + u32 chanspec = 0; +- u32 pre_ctl_chan = 0; ++ u32 prev_chan = 0; + u32 connected_cnt = wl_get_drv_status_all(wl, CONNECTED); + wl->vsdb_mode = false; + +@@ -9118,34 +8335,33 @@ static void wl_cfg80211_determine_vsdb_m + } + for_each_ndev(wl, iter, next) { + chanspec = 0; +- ctl_chan = 0; ++ chan = 0; + if (wl_get_drv_status(wl, CONNECTED, iter->ndev)) { + if (wldev_iovar_getint(iter->ndev, "chanspec", + (s32 *)&chanspec) == BCME_OK) { +- chanspec = wl_chspec_driver_to_host(chanspec); +- ctl_chan = wf_chspec_ctlchan(chanspec); +- wl_update_prof(wl, iter->ndev, NULL, +- &ctl_chan, WL_PROF_CHAN); +- } +- if (!wl->vsdb_mode) { +- if (!pre_ctl_chan && ctl_chan) +- pre_ctl_chan = ctl_chan; +- else if (pre_ctl_chan && (pre_ctl_chan != ctl_chan)) { +- wl->vsdb_mode = true; ++ chan = CHSPEC_CHANNEL(chanspec); ++ if (CHSPEC_IS40(chanspec)) { ++ if (CHSPEC_SB_UPPER(chanspec)) ++ chan += CH_10MHZ_APART; ++ else ++ chan -= CH_10MHZ_APART; + } ++ wl_update_prof(wl, iter->ndev, NULL, ++ &chan, WL_PROF_CHAN); + } ++ if (!prev_chan && chan) ++ prev_chan = chan; ++ else if (prev_chan && (prev_chan != chan)) ++ wl->vsdb_mode = true; + } + } +- WL_ERR(("%s concurrency is enabled\n", wl->vsdb_mode ? "Multi Channel" : "Same Channel")); + return; + } +- + static s32 wl_notifier_change_state(struct wl_priv *wl, struct net_info *_net_info, + enum wl_status state, bool set) + { + s32 pm = PM_FAST; + s32 err = BCME_OK; +- u32 mode; + u32 chan = 0; + struct net_info *iter, *next; + struct net_device *primary_dev = wl_to_prmry_ndev(wl); +@@ -9154,76 +8370,49 @@ static s32 wl_notifier_change_state(stru + + if (state != WL_STATUS_CONNECTED) + return 0; +- mode = wl_get_mode_by_netdev(wl, _net_info->ndev); ++ + if (set) { + wl_cfg80211_concurrent_roam(wl, 1); + +- if (mode == WL_MODE_AP) { +- ++ if (wl_get_mode_by_netdev(wl, _net_info->ndev) == WL_MODE_AP) { ++ pm = PM_OFF; ++ WL_DBG(("%s:AP power save %s\n", _net_info->ndev->name, ++ pm ? "enabled" : "disabled")); ++ if ((err = wldev_ioctl(_net_info->ndev, WLC_SET_PM, ++ &pm, sizeof(pm), true)) != 0) { ++ if (err == -ENODEV) ++ WL_DBG(("%s:net_device is not ready\n", ++ _net_info->ndev->name)); ++ else ++ WL_ERR(("%s:error (%d)\n", _net_info->ndev->name, err)); ++ } + if (wl_add_remove_eventmsg(primary_dev, WLC_E_P2P_PROBREQ_MSG, false)) + WL_ERR((" failed to unset WLC_E_P2P_PROPREQ_MSG\n")); ++ return 0; + } + wl_cfg80211_determine_vsdb_mode(wl); +- if (wl->vsdb_mode || _net_info->pm_block) { +- if (wl->pm_enable_work_on) { +- cancel_delayed_work_sync(&wl->pm_enable_work); +- wl->pm_enable_work_on = false; +- } +- /* save PM_FAST in _net_info to restore this +- * if _net_info->pm_block is false +- */ +- if (!_net_info->pm_block && (mode == WL_MODE_BSS)) { +- _net_info->pm = PM_FAST; +- _net_info->pm_restore = true; +- } +- pm = PM_OFF; +- for_each_ndev(wl, iter, next) { +- if (iter->pm_restore) +- continue; +- /* Save the current power mode */ +- err = wldev_ioctl(iter->ndev, WLC_GET_PM, &iter->pm, +- sizeof(iter->pm), false); +- WL_DBG(("%s:power save %s\n", iter->ndev->name, +- iter->pm ? "enabled" : "disabled")); +- if (!err && iter->pm) { +- iter->pm_restore = true; +- } +- +- } +- for_each_ndev(wl, iter, next) { +- if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM, &pm, +- sizeof(pm), true)) != 0) { +- if (err == -ENODEV) +- WL_DBG(("%s:netdev not ready\n", iter->ndev->name)); +- else +- WL_ERR(("%s:error (%d)\n", iter->ndev->name, err)); +- } else +- iter->ndev->ieee80211_ptr->ps = false; ++ pm = PM_OFF; ++ for_each_ndev(wl, iter, next) { ++ if ((!wl->vsdb_mode) && (iter->ndev != _net_info->ndev)) { ++ /* Do not touch the other interfaces power save ++ * if we are not in vsdb mode ++ */ ++ continue; + } +- } else { +- /* add PM Enable timer to go to power save mode +- * if supplicant control pm mode, it will be cleared or +- * updated by wl_cfg80211_set_power_mgmt() if not - for static IP & HW4 P2P, +- * PM will be configured when timer expired +- */ +- +- /* +- * before calling pm_enable_timer, we need to set PM -1 for all ndev +- */ +- pm = PM_OFF; +- +- for_each_ndev(wl, iter, next) { +- if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM, &pm, +- sizeof(pm), true)) != 0) { +- if (err == -ENODEV) +- WL_DBG(("%s:netdev not ready\n", iter->ndev->name)); +- else +- WL_ERR(("%s:error (%d)\n", iter->ndev->name, err)); +- } ++ /* Save the current power mode */ ++ iter->pm_restore = true; ++ err = wldev_ioctl(iter->ndev, WLC_GET_PM, &iter->pm, ++ sizeof(iter->pm), false); ++ WL_DBG(("%s:power save %s\n", iter->ndev->name, ++ iter->pm ? "enabled" : "disabled")); ++ if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM, &pm, ++ sizeof(pm), true)) != 0) { ++ if (err == -ENODEV) ++ WL_DBG(("%s:netdev not ready\n", iter->ndev->name)); ++ else ++ WL_ERR(("%s:error (%d)\n", iter->ndev->name, err)); ++ iter->ndev->ieee80211_ptr->ps = pm ? true: false; + } +- wl->pm_enable_work_on = true; +- schedule_delayed_work(&wl->pm_enable_work, +- msecs_to_jiffies(WL_PM_ENABLE_TIMEOUT)); + } + } + else { /* clear */ +@@ -9232,7 +8421,7 @@ static s32 wl_notifier_change_state(stru + wl_update_prof(wl, _net_info->ndev, NULL, &chan, WL_PROF_CHAN); + wl_cfg80211_determine_vsdb_mode(wl); + for_each_ndev(wl, iter, next) { +- if (iter->pm_restore && iter->pm) { ++ if (iter->pm_restore) { + WL_DBG(("%s:restoring power save %s\n", + iter->ndev->name, (iter->pm ? "enabled" : "disabled"))); + err = wldev_ioctl(iter->ndev, +@@ -9245,13 +8434,13 @@ static s32 wl_notifier_change_state(stru + break; + } + iter->pm_restore = 0; +- iter->ndev->ieee80211_ptr->ps = true; + } + } + wl_cfg80211_concurrent_roam(wl, 0); + } + return err; + } ++ + static s32 wl_init_scan(struct wl_priv *wl) + { + struct wl_iscan_ctrl *iscan = wl_to_iscan(wl); +@@ -9276,7 +8465,6 @@ static s32 wl_init_scan(struct wl_priv * + } else if (wl->escan_on) { + wl->evt_handler[WLC_E_ESCAN_RESULT] = wl_escan_handler; + wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE; +- wl_escan_init_sync_id(wl); + } + /* Init scan_timeout timer */ + init_timer(&wl->scan_timeout); +@@ -9342,7 +8530,7 @@ static void wl_deinit_priv(struct wl_pri + unregister_netdevice_notifier(&wl_cfg80211_netdev_notifier); + } + +-#if defined(WL_ENABLE_P2P_IF) ++#if defined(WLP2P) && defined(WL_ENABLE_P2P_IF) + static s32 wl_cfg80211_attach_p2p(void) + { + struct wl_priv *wl = wlcfg_drv_priv; +@@ -9350,7 +8538,7 @@ static s32 wl_cfg80211_attach_p2p(void) + WL_TRACE(("Enter \n")); + + if (wl_cfgp2p_register_ndev(wl) < 0) { +- WL_ERR(("P2P attach failed. \n")); ++ WL_ERR(("%s: P2P attach failed. \n", __func__)); + return -ENODEV; + } + +@@ -9360,16 +8548,10 @@ static s32 wl_cfg80211_attach_p2p(void) + static s32 wl_cfg80211_detach_p2p(void) + { + struct wl_priv *wl = wlcfg_drv_priv; +- struct wireless_dev *wdev; ++ struct wireless_dev *wdev = wl->p2p_wdev; + + WL_DBG(("Enter \n")); +- if (!wl) { +- WL_ERR(("Invalid Ptr\n")); +- return -EINVAL; +- } else +- wdev = wl->p2p_wdev; +- +- if (!wdev) { ++ if (!wdev || !wl) { + WL_ERR(("Invalid Ptr\n")); + return -EINVAL; + } +@@ -9383,7 +8565,7 @@ static s32 wl_cfg80211_detach_p2p(void) + + return 0; + } +-#endif /* WL_ENABLE_P2P_IF */ ++#endif /* defined(WLP2P) && defined(WL_ENABLE_P2P_IF) */ + + s32 wl_cfg80211_attach_post(struct net_device *ndev) + { +@@ -9400,15 +8582,17 @@ s32 wl_cfg80211_attach_post(struct net_d + return -EINVAL; + } + if (!wl_get_drv_status(wl, READY, ndev)) { +- if (wl->wdev && wl_cfgp2p_supported(wl, ndev)) { +- wl->wdev->wiphy->interface_modes |= ++ if (wl->wdev && ++ wl_cfgp2p_supported(wl, ndev)) { ++#if !defined(WL_ENABLE_P2P_IF) ++ wl->wdev->wiphy->interface_modes |= + (BIT(NL80211_IFTYPE_P2P_CLIENT)| + BIT(NL80211_IFTYPE_P2P_GO)); +- ++#endif + if ((err = wl_cfgp2p_init_priv(wl)) != 0) + goto fail; + +-#if defined(WL_ENABLE_P2P_IF) ++#if defined(WLP2P) && defined(WL_ENABLE_P2P_IF) + if (wl->p2p_net) { + /* Update MAC addr for p2p0 interface here. */ + memcpy(wl->p2p_net->dev_addr, ndev->dev_addr, ETH_ALEN); +@@ -9421,7 +8605,7 @@ s32 wl_cfg80211_attach_post(struct net_d + " Couldn't update the MAC Address for p2p0 \n")); + return -ENODEV; + } +-#endif /* WL_ENABLE_P2P_IF */ ++#endif /* defined(WLP2P) && (WL_ENABLE_P2P_IF) */ + + wl->p2p_supported = true; + } +@@ -9451,7 +8635,7 @@ s32 wl_cfg80211_attach(struct net_device + WL_ERR(("Could not allocate wireless device\n")); + return -ENOMEM; + } +- err = wl_setup_wiphy(wdev, dev, data); ++ err = wl_setup_wiphy(wdev, dev); + if (unlikely(err)) { + kfree(wdev); + return -ENOMEM; +@@ -9481,36 +8665,31 @@ s32 wl_cfg80211_attach(struct net_device + WL_ERR(("Failed to setup rfkill %d\n", err)); + goto cfg80211_attach_out; + } +-#ifdef DEBUGFS_CFG80211 +- err = wl_setup_debugfs(wl); +- if (err) { +- WL_ERR(("Failed to setup debugfs %d\n", err)); +- goto cfg80211_attach_out; +- } +-#endif + err = register_netdevice_notifier(&wl_cfg80211_netdev_notifier); + if (err) { + WL_ERR(("Failed to register notifierl %d\n", err)); + goto cfg80211_attach_out; + } + #if defined(COEX_DHCP) +- err = wl_cfg80211_btcoex_init(wl); +- if (err) ++ if (wl_cfg80211_btcoex_init(wl)) + goto cfg80211_attach_out; ++#endif ++#if defined(BSSCACHE) ++ wl_init_bss_cache_ctrl(&g_bss_cache_ctrl); + #endif + + wlcfg_drv_priv = wl; + +-#if defined(WL_ENABLE_P2P_IF) ++#if defined(WLP2P) && defined(WL_ENABLE_P2P_IF) + err = wl_cfg80211_attach_p2p(); + if (err) + goto cfg80211_attach_out; +-#endif /* WL_ENABLE_P2P_IF */ ++#endif + + return err; + + cfg80211_attach_out: +- wl_setup_rfkill(wl, FALSE); ++ err = wl_setup_rfkill(wl, FALSE); + wl_free_wdev(wl); + return err; + } +@@ -9526,29 +8705,28 @@ void wl_cfg80211_detach(void *para) + + #if defined(COEX_DHCP) + wl_cfg80211_btcoex_deinit(wl); +-#endif ++#endif + + wl_setup_rfkill(wl, FALSE); +-#ifdef DEBUGFS_CFG80211 +- wl_free_debugfs(wl); +-#endif + if (wl->p2p_supported) { + if (timer_pending(&wl->p2p->listen_timer)) + del_timer_sync(&wl->p2p->listen_timer); + wl_cfgp2p_deinit_priv(wl); + } + +-#if defined(WL_CFG80211_P2P_DEV_IF) +- wl_cfgp2p_del_p2p_disc_if(wl->p2p_wdev); +-#elif defined(WL_ENABLE_P2P_IF) ++#if defined(WLP2P) && defined(WL_ENABLE_P2P_IF) + wl_cfg80211_detach_p2p(); +-#endif /* WL_CFG80211_P2P_DEV_IF */ +- +- wl_cfg80211_ibss_vsie_free(wl); ++#endif + wl_deinit_priv(wl); + wlcfg_drv_priv = NULL; + wl_cfg80211_clear_parent_dev(); + wl_free_wdev(wl); ++#if defined(RSSIAVG) ++ wl_free_rssi_cache(&g_rssi_cache_ctrl); ++#endif ++#if defined(BSSCACHE) ++ wl_release_bss_cache_ctrl(&g_bss_cache_ctrl); ++#endif + /* PLEASE do NOT call any function after wl_free_wdev, the driver's private structure "wl", + * which is the private part of wiphy, has been freed in wl_free_wdev !!!!!!!!!!! + */ +@@ -9562,7 +8740,6 @@ static void wl_wakeup_event(struct wl_pr + } + } + +-#if (defined(WL_CFG80211_P2P_DEV_IF) || defined(WL_ENABLE_P2P_IF)) + static int wl_is_p2p_event(struct wl_event_q *e) + { + switch (e->etype) { +@@ -9577,8 +8754,8 @@ static int wl_is_p2p_event(struct wl_eve + case WLC_E_ACTION_FRAME_COMPLETE: + + if (e->emsg.ifidx != 0) { +- WL_TRACE(("P2P event(%d) on virtual interface(ifidx:%d)\n", +- e->etype, e->emsg.ifidx)); ++ WL_TRACE(("P2P Event on Virtual I/F (ifidx:%d) \n", ++ e->emsg.ifidx)); + /* We are only bothered about the P2P events received + * on primary interface. For rest of them return false + * so that it is sent over the interface corresponding +@@ -9586,30 +8763,33 @@ static int wl_is_p2p_event(struct wl_eve + */ + return FALSE; + } else { +- WL_TRACE(("P2P event(%d) on interface(ifidx:%d)\n", +- e->etype, e->emsg.ifidx)); ++ WL_TRACE(("P2P Event on Primary I/F (ifidx:%d)." ++ " Sent it to p2p0 \n", e->emsg.ifidx)); + return TRUE; + } + break; + + default: +- WL_TRACE(("NON-P2P event(%d) on interface(ifidx:%d)\n", ++ WL_TRACE(("NON-P2P Event %d on ifidx (ifidx:%d) \n", + e->etype, e->emsg.ifidx)); + return FALSE; + } + } +-#endif /* BCMDONGLEHOST && (WL_CFG80211_P2P_DEV_IF || WL_ENABLE_P2P_IF) */ + + static s32 wl_event_handler(void *data) + { ++ struct net_device *netdev; + struct wl_priv *wl = NULL; + struct wl_event_q *e; + tsk_ctl_t *tsk = (tsk_ctl_t *)data; +- bcm_struct_cfgdev *cfgdev = NULL; + + wl = (struct wl_priv *)tsk->parent; +- ++#ifndef USE_KTHREAD_API ++ DAEMONIZE("dhd_cfg80211_event"); ++ complete(&tsk->completed); ++#else + WL_ERR(("tsk Enter, tsk = 0x%08x\n", (unsigned int)tsk)); ++#endif + + while (down_interruptible (&tsk->sema) == 0) { + SMP_RD_BARRIER_DEPENDS(); +@@ -9621,31 +8801,15 @@ static s32 wl_event_handler(void *data) + * there is no corresponding bsscfg for P2P interface. Map it to p2p0 + * interface. + */ +-#if defined(WL_CFG80211_P2P_DEV_IF) +- if ((wl_is_p2p_event(e) == TRUE) && (wl->p2p_wdev)) { +- cfgdev = wl_to_p2p_wdev(wl); +- } else { +- cfgdev = ndev_to_wdev(dhd_idx2net((struct dhd_pub *)(wl->pub), +- e->emsg.ifidx)); +- } +-#elif defined(WL_ENABLE_P2P_IF) + if ((wl_is_p2p_event(e) == TRUE) && (wl->p2p_net)) { +- cfgdev = wl->p2p_net; ++ netdev = wl->p2p_net; + } else { +- cfgdev = dhd_idx2net((struct dhd_pub *)(wl->pub), +- e->emsg.ifidx); +- } +-#endif /* WL_CFG80211_P2P_DEV_IF */ +- +- if (!cfgdev) { +-#if defined(WL_CFG80211_P2P_DEV_IF) +- cfgdev = wl_to_prmry_wdev(wl); +-#elif defined(WL_ENABLE_P2P_IF) +- cfgdev = wl_to_prmry_ndev(wl); +-#endif /* WL_CFG80211_P2P_DEV_IF */ ++ netdev = dhd_idx2net((struct dhd_pub *)(wl->pub), e->emsg.ifidx); + } ++ if (!netdev) ++ netdev = wl_to_prmry_ndev(wl); + if (e->etype < WLC_E_LAST && wl->evt_handler[e->etype]) { +- wl->evt_handler[e->etype] (wl, cfgdev, &e->emsg, e->edata); ++ wl->evt_handler[e->etype] (wl, netdev, &e->emsg, e->edata); + } else { + WL_DBG(("Unknown Event (%d): ignoring\n", e->etype)); + } +@@ -9653,7 +8817,7 @@ static s32 wl_event_handler(void *data) + } + DHD_OS_WAKE_UNLOCK(wl->pub); + } +- WL_ERR(("was terminated\n")); ++ WL_ERR(("%s was terminated\n", __func__)); + complete_and_exit(&tsk->completed, 0); + return 0; + } +@@ -9915,7 +9079,6 @@ static int wl_construct_reginfo(struct w + bool update; + bool ht40_allowed; + u8 *pbuf = NULL; +- bool dfs_radar_disabled = FALSE; + + #define LOCAL_BUF_LEN 1024 + pbuf = kzalloc(LOCAL_BUF_LEN, GFP_KERNEL); +@@ -9924,7 +9087,7 @@ static int wl_construct_reginfo(struct w + WL_ERR(("failed to allocate local buf\n")); + return -ENOMEM; + } +- list = (wl_uint32_list_t *)(void *)pbuf; ++ list = (wl_uint32_list_t *)(void *) pbuf; + list->count = htod32(WL_NUMCHANSPECS); + + +@@ -9985,7 +9148,7 @@ static int wl_construct_reginfo(struct w + else + index = *n_cnt; + if (index < array_size) { +-#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) ++#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS) + band_chan_arr[index].center_freq = + ieee80211_channel_to_frequency(channel); + #else +@@ -9996,8 +9159,8 @@ static int wl_construct_reginfo(struct w + + if (CHSPEC_IS40(c) && ht40_allowed) { + /* assuming the order is HT20, HT40 Upper, +- * HT40 lower from chanspecs +- */ ++ HT40 lower from chanspecs ++ */ + u32 ht40_flag = band_chan_arr[index].flags & IEEE80211_CHAN_NO_HT40; + if (CHSPEC_SB_UPPER(c)) { + if (ht40_flag == IEEE80211_CHAN_NO_HT40) +@@ -10006,8 +9169,8 @@ static int wl_construct_reginfo(struct w + band_chan_arr[index].flags |= IEEE80211_CHAN_NO_HT40PLUS; + } else { + /* It should be one of +- * IEEE80211_CHAN_NO_HT40 or IEEE80211_CHAN_NO_HT40PLUS +- */ ++ IEEE80211_CHAN_NO_HT40 or IEEE80211_CHAN_NO_HT40PLUS ++ */ + band_chan_arr[index].flags &= ~IEEE80211_CHAN_NO_HT40; + if (ht40_flag == IEEE80211_CHAN_NO_HT40) + band_chan_arr[index].flags |= +@@ -10015,26 +9178,21 @@ static int wl_construct_reginfo(struct w + } + } else { + band_chan_arr[index].flags = IEEE80211_CHAN_NO_HT40; +- if (!dfs_radar_disabled) { +- if (band == IEEE80211_BAND_2GHZ) +- channel |= WL_CHANSPEC_BAND_2G; +- else +- channel |= WL_CHANSPEC_BAND_5G; +- channel |= WL_CHANSPEC_BW_20; +- channel = wl_chspec_host_to_driver(channel); +- err = wldev_iovar_getint(dev, "per_chan_info", &channel); +- if (!err) { +- if (channel & WL_CHAN_RADAR) +- band_chan_arr[index].flags |= +- (IEEE80211_CHAN_RADAR | +- IEEE80211_CHAN_NO_IBSS); +- if (channel & WL_CHAN_PASSIVE) +- band_chan_arr[index].flags |= +- IEEE80211_CHAN_PASSIVE_SCAN; +- } else if (err == BCME_UNSUPPORTED) { +- dfs_radar_disabled = TRUE; +- WL_ERR(("does not support per_chan_info\n")); +- } ++ if (band == IEEE80211_BAND_2GHZ) ++ channel |= WL_CHANSPEC_BAND_2G; ++ else ++ channel |= WL_CHANSPEC_BAND_5G; ++ channel |= WL_CHANSPEC_BW_20; ++ channel = wl_chspec_host_to_driver(channel); ++ err = wldev_iovar_getint(dev, "per_chan_info", &channel); ++ if (!err) { ++ if (channel & WL_CHAN_RADAR) ++ band_chan_arr[index].flags |= ++ (IEEE80211_CHAN_RADAR | ++ IEEE80211_CHAN_NO_IBSS); ++ if (channel & WL_CHAN_PASSIVE) ++ band_chan_arr[index].flags |= ++ IEEE80211_CHAN_PASSIVE_SCAN; + } + } + if (!update) +@@ -10079,8 +9237,6 @@ s32 wl_update_wiphybands(struct wl_priv + } + + wiphy = wl_to_wiphy(wl); +- wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; +- wiphy->bands[IEEE80211_BAND_5GHZ] = NULL; + + err = wldev_ioctl(dev, WLC_GET_BAND, &cur_band, + sizeof(s32), false); +@@ -10093,10 +9249,10 @@ s32 wl_update_wiphybands(struct wl_priv + if (unlikely(err)) { + WL_ERR(("error reading nmode (%d)\n", err)); + } else { +- /* For nmodeonly check bw cap */ ++ /* For nmodeonly check bw cap */ + err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap); + if (unlikely(err)) { +- WL_ERR(("error get mimo_bw_cap (%d)\n", err)); ++ WL_ERR(("error get mimo_bw_cap (%d)\n", err)); + } + } + +@@ -10107,6 +9263,7 @@ s32 wl_update_wiphybands(struct wl_priv + goto end_bands; + err = 0; + } ++ + nband = bandlist[0]; + + for (i = 1; i <= nband && i < ARRAYSIZE(bandlist); i++) { +@@ -10174,8 +9331,22 @@ static s32 __wl_cfg80211_up(struct wl_pr + err = dhd_monitor_init(wl->pub); + err = wl_invoke_iscan(wl); + ++#ifdef WL_HOST_BAND_MGMT ++ /* By default the curr_band is initialized to BAND_AUTO */ ++ if (wl_cfg80211_set_band(ndev, WLC_BAND_AUTO) < 0) { ++ WL_ERR(("roam_band set failed\n")); ++ err = -1; ++ } ++#endif /* WL_HOST_BAND_MGMT */ ++ ++#if defined(DHCP_SCAN_SUPPRESS) ++ /* wlan scan_supp timer and work thread info */ ++ init_timer(&wl->scan_supp_timer); ++ wl->scan_supp_timer.data = (ulong)wl; ++ wl->scan_supp_timer.function = wl_cfg80211_scan_supp_timerfunc; ++ INIT_WORK(&wl->wlan_work, wl_cfg80211_work_handler); ++#endif /* DHCP_SCAN_SUPPRESS */ + +- INIT_DELAYED_WORK(&wl->pm_enable_work, wl_cfg80211_work_handler); + wl_set_drv_status(wl, READY, ndev); + return err; + } +@@ -10186,38 +9357,21 @@ static s32 __wl_cfg80211_down(struct wl_ + unsigned long flags; + struct net_info *iter, *next; + struct net_device *ndev = wl_to_prmry_ndev(wl); +-#if defined(WL_CFG80211) && defined(WL_ENABLE_P2P_IF) + struct net_device *p2p_net = wl->p2p_net; +-#endif /* WL_CFG80211 && WL_ENABLE_P2P_IF */ +- u32 bssidx = 0; +-#ifdef PROP_TXSTATUS_VSDB +- dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); +-#endif /* PROP_TXSTATUS_VSDB */ ++ u32 bssidx = wl_cfgp2p_find_idx(wl, ndev); + WL_DBG(("In\n")); +- if (wl->pm_enable_work_on) { +- cancel_delayed_work_sync(&wl->pm_enable_work); +- wl->pm_enable_work_on = false; +- } +- +- if (wl->p2p_supported) { +- wl_clr_p2p_status(wl, GO_NEG_PHASE); +-#ifdef PROP_TXSTATUS_VSDB +- if (wl->p2p->vif_created) { +- if (dhd->wlfc_enabled && wl->wlfc_on) { +- dhd->wlfc_enabled = false; +- dhd_wlfc_deinit(dhd); +- if (dhd->plat_deinit) +- dhd->plat_deinit((void *)dhd); +- wl->wlfc_on = false; +- } +- } +-#endif /* PROP_TXSTATUS_VSDB */ +- } + ++#if defined(DHCP_SCAN_SUPPRESS) ++ /* Force clear of scan_suppress */ ++ if (wl->scan_suppressed) ++ wl_cfg80211_scan_suppress(ndev, 0); ++ if (timer_pending(&wl->scan_supp_timer)) ++ del_timer_sync(&wl->scan_supp_timer); ++ cancel_work_sync(&wl->wlan_work); ++#endif /* DHCP_SCAN_SUPPRESS */ + +- /* If primary BSS is operational (for e.g SoftAP), bring it down */ +- if (!(wl_cfgp2p_find_idx(wl, ndev, &bssidx)) && +- wl_cfgp2p_bss_isup(ndev, bssidx)) { ++ /* If BSS is operational (e.g SoftAp), bring it down */ ++ if (wl_cfgp2p_bss_isup(ndev, bssidx)) { + if (wl_cfgp2p_bss(wl, ndev, bssidx, 0) < 0) + WL_ERR(("BSS down failed \n")); + } +@@ -10225,10 +9379,10 @@ static s32 __wl_cfg80211_down(struct wl_ + /* Check if cfg80211 interface is already down */ + if (!wl_get_drv_status(wl, READY, ndev)) + return err; /* it is even not ready */ ++ + for_each_ndev(wl, iter, next) + wl_set_drv_status(wl, SCAN_ABORTING, iter->ndev); + +- + wl_term_iscan(wl); + spin_lock_irqsave(&wl->cfgdrv_lock, flags); + if (wl->scan_request) { +@@ -10249,10 +9403,8 @@ static s32 __wl_cfg80211_down(struct wl_ + } + wl_to_prmry_ndev(wl)->ieee80211_ptr->iftype = + NL80211_IFTYPE_STATION; +-#if defined(WL_CFG80211) && defined(WL_ENABLE_P2P_IF) + if (p2p_net) + dev_close(p2p_net); +-#endif /* WL_CFG80211 && WL_ENABLE_P2P_IF */ + DNGL_FUNC(dhd_cfg80211_down, (wl)); + wl_flush_eq(wl); + wl_link_down(wl); +@@ -10310,6 +9462,13 @@ int wl_cfg80211_hang(struct net_device * + + WL_ERR(("In : chip crash eventing\n")); + cfg80211_disconnected(dev, reason, NULL, 0, GFP_KERNEL); ++#if defined(RSSIAVG) ++ wl_free_rssi_cache(&g_rssi_cache_ctrl); ++#endif ++#if defined(BSSCACHE) ++ wl_free_bss_cache(&g_bss_cache_ctrl); ++ wl_run_bss_cache_timer(&g_bss_cache_ctrl, 0); ++#endif + if (wl != NULL) { + wl_link_down(wl); + } +@@ -10325,6 +9484,13 @@ s32 wl_cfg80211_down(void *para) + WL_DBG(("In\n")); + wl = wlcfg_drv_priv; + mutex_lock(&wl->usr_sync); ++#if defined(RSSIAVG) ++ wl_free_rssi_cache(&g_rssi_cache_ctrl); ++#endif ++#if defined(BSSCACHE) ++ wl_free_bss_cache(&g_bss_cache_ctrl); ++ wl_run_bss_cache_timer(&g_bss_cache_ctrl, 0); ++#endif + err = __wl_cfg80211_down(wl); + mutex_unlock(&wl->usr_sync); + +@@ -10403,14 +9569,13 @@ wl_update_prof(struct wl_priv *wl, struc + break; + case WL_PROF_CHAN: + profile->channel = *(u32*)data; +- break; + default: + err = -EOPNOTSUPP; + break; + } + spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); + +- if (err == -EOPNOTSUPP) ++ if (err == EOPNOTSUPP) + WL_ERR(("unsupported item (%d)\n", item)); + + return err; +@@ -10461,29 +9626,6 @@ static __used s32 wl_add_ie(struct wl_pr + return err; + } + +-static void wl_update_hidden_ap_ie(struct wl_bss_info *bi, u8 *ie_stream, u32 *ie_size) +-{ +- u8 *ssidie; +- ssidie = (u8 *)cfg80211_find_ie(WLAN_EID_SSID, ie_stream, *ie_size); +- if (!ssidie) +- return; +- if (ssidie[1] != bi->SSID_len) { +- if (ssidie[1]) { +- WL_ERR(("%s: Wrong SSID len: %d != %d\n", +- __FUNCTION__, ssidie[1], bi->SSID_len)); +- return; +- } +- memmove(ssidie + bi->SSID_len + 2, ssidie + 2, *ie_size - (ssidie + 2 - ie_stream)); +- memcpy(ssidie + 2, bi->SSID, bi->SSID_len); +- *ie_size = *ie_size + bi->SSID_len; +- ssidie[1] = bi->SSID_len; +- return; +- } +- if (*(ssidie + 2) == '\0') +- memcpy(ssidie + 2, bi->SSID, bi->SSID_len); +- return; +-} +- + static s32 wl_mrg_ie(struct wl_priv *wl, u8 *ie_stream, u16 ie_size) + { + struct wl_ie *ie = wl_to_ie(wl); +@@ -10556,9 +9698,9 @@ static void wl_init_eq_lock(struct wl_pr + static void wl_delay(u32 ms) + { + if (in_atomic() || (ms < jiffies_to_msecs(1))) { +- OSL_DELAY(ms*1000); ++ mdelay(ms); + } else { +- OSL_SLEEP(ms); ++ msleep(ms); + } + } + +@@ -10609,7 +9751,7 @@ s32 wl_cfg80211_channel_to_freq(u32 chan + { + int freq = 0; + +-#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) ++#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS) + freq = ieee80211_channel_to_frequency(channel); + #else + { +@@ -10624,90 +9766,6 @@ s32 wl_cfg80211_channel_to_freq(u32 chan + return freq; + } + +- +-#ifdef WLTDLS +-static s32 +-wl_tdls_event_handler(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev, +- const wl_event_msg_t *e, void *data) { +- +- struct net_device *ndev = NULL; +- u32 reason = ntoh32(e->reason); +- s8 *msg = NULL; +- +- ndev = cfgdev_to_wlc_ndev(cfgdev, wl); +- +- switch (reason) { +- case WLC_E_TDLS_PEER_DISCOVERED : +- msg = " TDLS PEER DISCOVERD "; +- break; +- case WLC_E_TDLS_PEER_CONNECTED : +- msg = " TDLS PEER CONNECTED "; +- break; +- case WLC_E_TDLS_PEER_DISCONNECTED : +- msg = "TDLS PEER DISCONNECTED "; +- break; +- } +- if (msg) { +- WL_ERR(("%s: " MACDBG " on %s ndev\n", msg, MAC2STRDBG((u8*)(&e->addr)), +- (wl_to_prmry_ndev(wl) == ndev) ? "primary" : "secondary")); +- } +- return 0; +- +-} +-#endif /* WLTDLS */ +- +-#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0) +-static s32 +-wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, +- u8 *peer, enum nl80211_tdls_operation oper) +-{ +- s32 ret = 0; +-#ifdef WLTDLS +- struct wl_priv *wl = wlcfg_drv_priv; +- tdls_iovar_t info; +- +- memset(&info, 0, sizeof(tdls_iovar_t)); +- if (peer) +- memcpy(&info.ea, peer, ETHER_ADDR_LEN); +- switch (oper) { +- case NL80211_TDLS_DISCOVERY_REQ: +- /* turn on TDLS */ +- ret = dhd_tdls_enable(dev, true, false, NULL); +- if (ret < 0) +- return ret; +- info.mode = TDLS_MANUAL_EP_DISCOVERY; +- break; +- case NL80211_TDLS_SETUP: +- /* auto mode on */ +- ret = dhd_tdls_enable(dev, true, true, (struct ether_addr *)peer); +- if (ret < 0) +- return ret; +- break; +- case NL80211_TDLS_TEARDOWN: +- info.mode = TDLS_MANUAL_EP_DELETE; +- /* auto mode off */ +- ret = dhd_tdls_enable(dev, true, false, (struct ether_addr *)peer); +- if (ret < 0) +- return ret; +- break; +- default: +- WL_ERR(("Unsupported operation : %d\n", oper)); +- goto out; +- } +- +- if (info.mode) { +- ret = wldev_iovar_setbuf(dev, "tdls_endpoint", &info, sizeof(info), +- wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync); +- if (ret) { +- WL_ERR(("tdls_endpoint error %d\n", ret)); +- } +- } +-out: +-#endif /* WLTDLS */ +- return ret; +-} +-#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0) */ +- + s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len, + enum wl_management_type type) + { +@@ -10719,16 +9777,14 @@ s32 wl_cfg80211_set_wps_p2p_ie(struct ne + s32 pktflag = 0; + wl = wlcfg_drv_priv; + +- if (wl_get_drv_status(wl, AP_CREATING, net)) { +- /* Vendor IEs should be set to FW +- * after SoftAP interface is brought up +- */ +- goto exit; +- } else if (wl_get_drv_status(wl, AP_CREATED, net)) { ++ if (wl_get_drv_status(wl, AP_CREATING, net) || ++ wl_get_drv_status(wl, AP_CREATED, net)) { + ndev = net; + bssidx = 0; + } else if (wl->p2p) { +- net = ndev_to_wlc_ndev(net, wl); ++ if (net == wl->p2p_net) { ++ net = wl_to_prmry_ndev(wl); ++ } + if (!wl->p2p->on) { + get_primary_mac(wl, &primary_mac); + wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr, +@@ -10773,7 +9829,6 @@ exit: + return ret; + } + +- + static const struct rfkill_ops wl_rfkill_ops = { + .set_block = wl_rfkill_set + }; +@@ -10828,128 +9883,6 @@ err_out: + return err; + } + +-#ifdef DEBUGFS_CFG80211 +-/** +-* Format : echo "SCAN:1 DBG:1" > /sys/kernel/debug/dhd/debug_level +-* to turn on SCAN and DBG log. +-* To turn off SCAN partially, echo "SCAN:0" > /sys/kernel/debug/dhd/debug_level +-* To see current setting of debug level, +-* cat /sys/kernel/debug/dhd/debug_level +-*/ +-static ssize_t +-wl_debuglevel_write(struct file *file, const char __user *userbuf, +- size_t count, loff_t *ppos) +-{ +- char tbuf[S_SUBLOGLEVEL * ARRAYSIZE(sublogname_map)], sublog[S_SUBLOGLEVEL]; +- char *params, *token, *colon; +- uint i, tokens, log_on = 0; +- memset(tbuf, 0, sizeof(tbuf)); +- memset(sublog, 0, sizeof(sublog)); +- if (copy_from_user(&tbuf, userbuf, min_t(size_t, sizeof(tbuf), count))) +- return -EFAULT; +- +- params = &tbuf[0]; +- colon = strchr(params, '\n'); +- if (colon != NULL) +- *colon = '\0'; +- while ((token = strsep(¶ms, " ")) != NULL) { +- memset(sublog, 0, sizeof(sublog)); +- if (token == NULL || !*token) +- break; +- if (*token == '\0') +- continue; +- colon = strchr(token, ':'); +- if (colon != NULL) { +- *colon = ' '; +- } +- tokens = sscanf(token, "%s %u", sublog, &log_on); +- if (colon != NULL) +- *colon = ':'; +- +- if (tokens == 2) { +- for (i = 0; i < ARRAYSIZE(sublogname_map); i++) { +- if (!strncmp(sublog, sublogname_map[i].sublogname, +- strlen(sublogname_map[i].sublogname))) { +- if (log_on) +- wl_dbg_level |= +- (sublogname_map[i].log_level); +- else +- wl_dbg_level &= +- ~(sublogname_map[i].log_level); +- } +- } +- } else +- WL_ERR(("%s: can't parse '%s' as a " +- "SUBMODULE:LEVEL (%d tokens)\n", +- tbuf, token, tokens)); +- +- +- } +- return count; +-} +- +-static ssize_t +-wl_debuglevel_read(struct file *file, char __user *user_buf, +- size_t count, loff_t *ppos) +-{ +- char *param; +- char tbuf[S_SUBLOGLEVEL * ARRAYSIZE(sublogname_map)]; +- uint i; +- memset(tbuf, 0, sizeof(tbuf)); +- param = &tbuf[0]; +- for (i = 0; i < ARRAYSIZE(sublogname_map); i++) { +- param += snprintf(param, sizeof(tbuf) - 1, "%s:%d ", +- sublogname_map[i].sublogname, +- (wl_dbg_level & sublogname_map[i].log_level) ? 1 : 0); +- } +- *param = '\n'; +- return simple_read_from_buffer(user_buf, count, ppos, tbuf, strlen(&tbuf[0])); +- +-} +-static const struct file_operations fops_debuglevel = { +- .open = NULL, +- .write = wl_debuglevel_write, +- .read = wl_debuglevel_read, +- .owner = THIS_MODULE, +- .llseek = NULL, +-}; +- +-static s32 wl_setup_debugfs(struct wl_priv *wl) +-{ +- s32 err = 0; +- struct dentry *_dentry; +- if (!wl) +- return -EINVAL; +- wl->debugfs = debugfs_create_dir(KBUILD_MODNAME, NULL); +- if (!wl->debugfs || IS_ERR(wl->debugfs)) { +- if (wl->debugfs == ERR_PTR(-ENODEV)) +- WL_ERR(("Debugfs is not enabled on this kernel\n")); +- else +- WL_ERR(("Can not create debugfs directory\n")); +- wl->debugfs = NULL; +- goto exit; +- +- } +- _dentry = debugfs_create_file("debug_level", S_IRUSR | S_IWUSR, +- wl->debugfs, wl, &fops_debuglevel); +- if (!_dentry || IS_ERR(_dentry)) { +- WL_ERR(("failed to create debug_level debug file\n")); +- wl_free_debugfs(wl); +- } +-exit: +- return err; +-} +-static s32 wl_free_debugfs(struct wl_priv *wl) +-{ +- if (!wl) +- return -EINVAL; +- if (wl->debugfs) +- debugfs_remove_recursive(wl->debugfs); +- wl->debugfs = NULL; +- return 0; +-} +-#endif /* DEBUGFS_CFG80211 */ +- + struct device *wl_cfg80211_get_parent_dev(void) + { + return cfg80211_parent_dev; +@@ -10965,27 +9898,13 @@ static void wl_cfg80211_clear_parent_dev + cfg80211_parent_dev = NULL; + } + +-void get_primary_mac(struct wl_priv *wl, struct ether_addr *mac) ++static void get_primary_mac(struct wl_priv *wl, struct ether_addr *mac) + { + wldev_iovar_getbuf_bsscfg(wl_to_prmry_ndev(wl), "cur_etheraddr", NULL, + 0, wl->ioctl_buf, WLC_IOCTL_SMLEN, 0, &wl->ioctl_buf_sync); + memcpy(mac->octet, wl->ioctl_buf, ETHER_ADDR_LEN); + } + +-static bool check_dev_role_integrity(struct wl_priv *wl, u32 dev_role) +-{ +- dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); +- if (((dev_role == NL80211_IFTYPE_AP) && +- !(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) || +- ((dev_role == NL80211_IFTYPE_P2P_GO) && +- !(dhd->op_mode & DHD_FLAG_P2P_GO_MODE))) +- { +- WL_ERR(("device role select failed\n")); +- return false; +- } +- return true; +-} +- + int wl_cfg80211_do_driver_init(struct net_device *net) + { + struct wl_priv *wl = *(struct wl_priv **)netdev_priv(net); +@@ -10999,17 +9918,17 @@ int wl_cfg80211_do_driver_init(struct ne + return 0; + } + +-void wl_cfg80211_enable_trace(bool set, u32 level) ++void wl_cfg80211_enable_trace(u32 level) + { +- if (set) +- wl_dbg_level = level & WL_DBG_LEVEL; +- else +- wl_dbg_level |= (WL_DBG_LEVEL & level); ++ wl_dbg_level = level; ++ printk("%s: wl_dbg_level = 0x%x\n", __FUNCTION__, wl_dbg_level); + } + ++#if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \ ++ 2, 0)) + static s32 + wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, +- bcm_struct_cfgdev *cfgdev, u64 cookie) ++ struct net_device *dev, u64 cookie) + { + /* CFG80211 checks for tx_cancel_wait callback when ATTR_DURATION + * is passed with CMD_FRAME. This callback is supposed to cancel +@@ -11019,6 +9938,7 @@ wl_cfg80211_mgmt_tx_cancel_wait(struct w + + return 0; + } ++#endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL >= 3.2.0 */ + + #ifdef WL11U + bcm_tlv_t * +@@ -11066,8 +9986,7 @@ wl_cfg80211_add_iw_ie(struct wl_priv *wl + + if (wl->iw_ie_len == data_len && !memcmp(wl->iw_ie, data, data_len)) { + WL_ERR(("Previous IW IE is equals to current IE\n")); +- err = BCME_OK; +- goto exit; ++ return err; + } + + strncpy(ie_setbuf->cmd, "add", VNDR_IE_CMD_LEN - 1); +@@ -11091,7 +10010,7 @@ wl_cfg80211_add_iw_ie(struct wl_priv *wl + wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync); + + if (err != BCME_OK) +- goto exit; ++ return err; + } + + ie_setbuf->ie_buffer.ie_list[0].ie_data.len = data_len; +@@ -11108,67 +10027,101 @@ wl_cfg80211_add_iw_ie(struct wl_priv *wl + err = wldev_iovar_setint_bsscfg(ndev, "grat_arp", 1, bssidx); + } + +-exit: +- if (ie_setbuf) +- kfree(ie_setbuf); ++ kfree(ie_setbuf); + return err; + } + #endif /* WL11U */ + +-static void wl_cfg80211_work_handler(struct work_struct * work) ++#ifdef WL_HOST_BAND_MGMT ++s32 ++wl_cfg80211_set_band(struct net_device *ndev, int band) + { +- struct wl_priv *wl = NULL; +- struct net_info *iter, *next; +- s32 err = BCME_OK; +- s32 pm = PM_FAST; ++ struct wl_priv *wl = wlcfg_drv_priv; ++ int ret = 0; ++ char ioctl_buf[50]; + +- wl = container_of(work, struct wl_priv, pm_enable_work.work); +- WL_DBG(("Enter \n")); +- if (wl->pm_enable_work_on) { +- wl->pm_enable_work_on = false; +- for_each_ndev(wl, iter, next) { +- if (!wl_get_drv_status(wl, CONNECTED, iter->ndev) || +- (wl_get_mode_by_netdev(wl, iter->ndev) != WL_MODE_BSS)) +- continue; +- if (iter->ndev) { +- if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM, +- &pm, sizeof(pm), true)) != 0) { +- if (err == -ENODEV) +- WL_DBG(("%s:netdev not ready\n", iter->ndev->name)); +- else +- WL_ERR(("%s:error (%d)\n", iter->ndev->name, err)); +- } else +- iter->ndev->ieee80211_ptr->ps = true; +- } +- } ++ if ((band < WLC_BAND_AUTO) || (band > WLC_BAND_2G)) { ++ WL_ERR(("Invalid band\n")); ++ return -EINVAL; + } ++ ++ if ((ret = wldev_iovar_setbuf(ndev, "roam_band", &band, ++ sizeof(int), ioctl_buf, sizeof(ioctl_buf), NULL)) < 0) { ++ WL_ERR(("seting roam_band failed code=%d\n", ret)); ++ return ret; ++ } ++ ++ WL_DBG(("Setting band to %d\n", band)); ++ wl->curr_band = band; ++ ++ return 0; + } ++#endif /* WL_HOST_BAND_MGMT */ + +-u8 +-wl_get_action_category(void *frame, u32 frame_len) ++#if defined(DHCP_SCAN_SUPPRESS) ++static void wl_cfg80211_scan_supp_timerfunc(ulong data) + { +- u8 category; +- u8 *ptr = (u8 *)frame; +- if (frame == NULL) +- return DOT11_ACTION_CAT_ERR_MASK; +- if (frame_len < DOT11_ACTION_HDR_LEN) +- return DOT11_ACTION_CAT_ERR_MASK; +- category = ptr[DOT11_ACTION_CAT_OFF]; +- WL_INFO(("Action Category: %d\n", category)); +- return category; ++ struct wl_priv *wl = (struct wl_priv *)data; ++ ++ WL_DBG(("Enter \n")); ++ schedule_work(&wl->wlan_work); + } + +-int +-wl_get_public_action(void *frame, u32 frame_len, u8 *ret_action) ++static void wl_cfg80211_work_handler(struct work_struct *work) + { +- u8 *ptr = (u8 *)frame; +- if (frame == NULL || ret_action == NULL) +- return BCME_ERROR; +- if (frame_len < DOT11_ACTION_HDR_LEN) +- return BCME_ERROR; +- if (DOT11_ACTION_CAT_PUBLIC != wl_get_action_category(frame, frame_len)) +- return BCME_ERROR; +- *ret_action = ptr[DOT11_ACTION_ACT_OFF]; +- WL_INFO(("Public Action : %d\n", *ret_action)); +- return BCME_OK; ++ struct wl_priv *wl = wlcfg_drv_priv; ++ ++ wl = container_of(work, struct wl_priv, wlan_work); ++ ++ if (!wl) { ++ WL_ERR(("wl_priv ptr NULL\n")); ++ return; ++ } ++ ++ if (wl->scan_suppressed) { ++ /* There is pending scan_suppress. Clean it */ ++ WL_ERR(("Clean up from timer after %d msec\n", WL_SCAN_SUPPRESS_TIMEOUT)); ++ wl_cfg80211_scan_suppress(wl_to_prmry_ndev(wl), 0); ++ } ++} ++ ++int wl_cfg80211_scan_suppress(struct net_device *dev, int suppress) ++{ ++ struct wl_priv *wl = wlcfg_drv_priv; ++ int ret = 0; ++ ++ if (!dev || !wl || ((suppress != 0) && (suppress != 1))) ++ return -EINVAL; ++ ++ if (suppress == wl->scan_suppressed) { ++ WL_DBG(("No change in scan_suppress state. Ignoring cmd..\n")); ++ return 0; ++ } ++ ++ if (timer_pending(&wl->scan_supp_timer)) ++ del_timer_sync(&wl->scan_supp_timer); ++ ++ if ((ret = wldev_ioctl(dev, WLC_SET_SCANSUPPRESS, ++ &suppress, sizeof(int), true)) < 0) { ++ WL_ERR(("Scan suppress setting failed ret:%d \n", ret)); ++ } else { ++ WL_DBG(("Scan suppress %s \n", suppress ? "Enabled" : "Disabled")); ++ wl->scan_suppressed = suppress; ++ } ++ ++ /* If scan_suppress is set, Start a timer to monitor it (just incase) */ ++ if (wl->scan_suppressed) { ++ if (ret) { ++ WL_ERR(("Retry scan_suppress reset at a later time \n")); ++ mod_timer(&wl->scan_supp_timer, ++ jiffies + msecs_to_jiffies(WL_SCAN_SUPPRESS_RETRY)); ++ } else { ++ WL_DBG(("Start wlan_timer to clear of scan_suppress \n")); ++ mod_timer(&wl->scan_supp_timer, ++ jiffies + msecs_to_jiffies(WL_SCAN_SUPPRESS_TIMEOUT)); ++ } ++ } ++ ++ return ret; + } ++#endif /* DHCP_SCAN_SUPPRESS */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/wl_cfg80211.h linux-sunxi-new/drivers/net/wireless/bcmdhd/wl_cfg80211.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/wl_cfg80211.h 2014-01-27 01:30:30.100433249 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/wl_cfg80211.h 2014-02-15 00:43:44.791014047 +0100 +@@ -1,7 +1,7 @@ + /* + * Linux cfg80211 driver + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -21,7 +21,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: wl_cfg80211.h 418267 2013-08-14 12:49:52Z $ ++ * $Id: wl_cfg80211.h 374275 2012-12-12 11:44:18Z $ + */ + + #ifndef _wl_cfg80211_h_ +@@ -44,12 +44,12 @@ struct wl_security; + struct wl_ibss; + + +-#define htod32(i) (i) +-#define htod16(i) (i) +-#define dtoh32(i) (i) +-#define dtoh16(i) (i) +-#define htodchanspec(i) (i) +-#define dtohchanspec(i) (i) ++#define htod32(i) i ++#define htod16(i) i ++#define dtoh32(i) i ++#define dtoh16(i) i ++#define htodchanspec(i) i ++#define dtohchanspec(i) i + + #define WL_DBG_NONE 0 + #define WL_DBG_P2P_ACTION (1 << 5) +@@ -138,7 +138,7 @@ do { \ + #define WL_SCAN_IE_LEN_MAX 2048 + #define WL_BSS_INFO_MAX 2048 + #define WL_ASSOC_INFO_MAX 512 +-#define WL_IOCTL_LEN_MAX 2048 ++#define WL_IOCTL_LEN_MAX 1024 + #define WL_EXTRA_BUF_MAX 2048 + #define WL_ISCAN_BUF_MAX 2048 + #define WL_ISCAN_TIMER_INTERVAL_MS 3000 +@@ -146,7 +146,7 @@ do { \ + #define WL_AP_MAX 256 + #define WL_FILE_NAME_MAX 256 + #define WL_DWELL_TIME 200 +-#define WL_MED_DWELL_TIME 400 ++#define WL_MED_DWELL_TIME 400 + #define WL_MIN_DWELL_TIME 100 + #define WL_LONG_DWELL_TIME 1000 + #define IFACE_MAX_CNT 2 +@@ -156,24 +156,19 @@ do { \ + #define WL_SCAN_JOIN_PASSIVE_DWELL_TIME_MS 400 + #define WL_AF_TX_MAX_RETRY 5 + +-#define WL_AF_SEARCH_TIME_MAX 450 +-#define WL_AF_TX_EXTRA_TIME_MAX 200 +- + #define WL_SCAN_TIMER_INTERVAL_MS 8000 /* Scan timeout */ + #define WL_CHANNEL_SYNC_RETRY 5 + #define WL_INVALID -1 + + /* Bring down SCB Timeout to 20secs from 60secs default */ + #ifndef WL_SCB_TIMEOUT +-#define WL_SCB_TIMEOUT 20 ++#define WL_SCB_TIMEOUT 20 + #endif + + /* SCAN_SUPPRESS timer values in ms */ + #define WL_SCAN_SUPPRESS_TIMEOUT 31000 /* default Framwork DHCP timeout is 30 sec */ + #define WL_SCAN_SUPPRESS_RETRY 3000 + +-#define WL_PM_ENABLE_TIMEOUT 3000 +- + /* driver status */ + enum wl_status { + WL_STATUS_READY = 0, +@@ -274,8 +269,8 @@ struct wl_conf { + struct ieee80211_channel channel; + }; + +-typedef s32(*EVENT_HANDLER) (struct wl_priv *wl, bcm_struct_cfgdev *cfgdev, +- const wl_event_msg_t *e, void *data); ++typedef s32(*EVENT_HANDLER) (struct wl_priv *wl, ++ struct net_device *ndev, const wl_event_msg_t *e, void *data); + + /* bss inform structure for cfg80211 interface */ + struct wl_cfg80211_bss_info { +@@ -405,7 +400,7 @@ struct escan_info { + #if defined(STATIC_WL_PRIV_STRUCT) + #ifndef CONFIG_DHD_USE_STATIC_BUF + #error STATIC_WL_PRIV_STRUCT should be used with CONFIG_DHD_USE_STATIC_BUF +-#endif /* CONFIG_DHD_USE_STATIC_BUF */ ++#endif + u8 *escan_buf; + #else + u8 escan_buf[ESCAN_BUF_SIZE]; +@@ -472,14 +467,11 @@ struct parsed_ies { + }; + + +- + #ifdef WL11U + /* Max length of Interworking element */ + #define IW_IES_MAX_BUF_LEN 9 + #endif +-#ifdef WLFBT +-#define FBT_KEYLEN 32 +-#endif ++ + #define MAX_EVENT_BUF_NUM 16 + typedef struct wl_eventmsg_buf { + u16 num; +@@ -494,7 +486,6 @@ struct wl_priv { + struct wireless_dev *wdev; /* representing wl cfg80211 device */ + + struct wireless_dev *p2p_wdev; /* representing wl cfg80211 device for P2P */ +- + struct net_device *p2p_net; /* reference to p2p0 interface */ + + struct wl_conf *conf; +@@ -527,9 +518,7 @@ struct wl_priv { + #else + struct wl_connect_info conn_info; + #endif +-#ifdef DEBUGFS_CFG80211 +- struct dentry *debugfs; +-#endif /* DEBUGFS_CFG80211 */ ++ + struct wl_pmk_list *pmk_list; /* wpa2 pmk list */ + tsk_ctl_t event_tsk; /* task of main event handler thread */ + void *pub; +@@ -556,7 +545,7 @@ struct wl_priv { + bool wlfc_on; + bool vsdb_mode; + bool roamoff_on_concurrent; +- u8 *ioctl_buf; /* ioctl buffer */ ++ u8 *ioctl_buf; /* ioctl buffer */ + struct mutex ioctl_buf_sync; + u8 *escan_ioctl_buf; + u8 *extra_buf; /* maily to grab assoc information */ +@@ -589,14 +578,13 @@ struct wl_priv { + #ifdef WL_SCHED_SCAN + struct cfg80211_sched_scan_request *sched_scan_req; /* scheduled scan req */ + #endif /* WL_SCHED_SCAN */ ++#ifdef WL_HOST_BAND_MGMT ++ u8 curr_band; ++#endif /* WL_HOST_BAND_MGMT */ + bool scan_suppressed; + struct timer_list scan_supp_timer; + struct work_struct wlan_work; + struct mutex event_sync; /* maily for up/down synchronization */ +- bool pm_enable_work_on; +- struct delayed_work pm_enable_work; +- vndr_ie_setbuf_t *ibss_vsie; /* keep the VSIE for IBSS */ +- int ibss_vsie_len; + }; + + +@@ -691,8 +679,8 @@ wl_set_status_all(struct wl_priv *wl, s3 + return; /* change all status is not allowed */ + default: + return; /* unknown operation */ ++ } + } +- } + } + static inline void + wl_set_status_by_netdev(struct wl_priv *wl, s32 status, +@@ -787,47 +775,7 @@ wl_get_netinfo_by_netdev(struct wl_priv + } + #define wl_to_wiphy(w) (w->wdev->wiphy) + #define wl_to_prmry_ndev(w) (w->wdev->netdev) +-#define wl_to_prmry_wdev(w) (w->wdev) +-#define wl_to_p2p_wdev(w) (w->p2p_wdev) + #define ndev_to_wl(n) (wdev_to_wl(n->ieee80211_ptr)) +-#define ndev_to_wdev(ndev) (ndev->ieee80211_ptr) +-#define wdev_to_ndev(wdev) (wdev->netdev) +- +-#if defined(WL_ENABLE_P2P_IF) +-#define ndev_to_wlc_ndev(ndev, wl) ((ndev == wl->p2p_net) ? \ +- wl_to_prmry_ndev(wl) : ndev) +-#else +-#define ndev_to_wlc_ndev(ndev, wl) (ndev) +-#endif /* WL_ENABLE_P2P_IF */ +- +-#if defined(WL_CFG80211_P2P_DEV_IF) +-#define wdev_to_wlc_ndev(wdev, wl) \ +- ((wdev->iftype == NL80211_IFTYPE_P2P_DEVICE) ? \ +- wl_to_prmry_ndev(wl) : wdev_to_ndev(wdev)) +-#define cfgdev_to_wlc_ndev(cfgdev, wl) wdev_to_wlc_ndev(cfgdev, wl) +-#elif defined(WL_ENABLE_P2P_IF) +-#define cfgdev_to_wlc_ndev(cfgdev, wl) ndev_to_wlc_ndev(cfgdev, wl) +-#else +-#define cfgdev_to_wlc_ndev(cfgdev, wl) (cfgdev) +-#endif /* WL_CFG80211_P2P_DEV_IF */ +- +-#if defined(WL_CFG80211_P2P_DEV_IF) +-#define ndev_to_cfgdev(ndev) ndev_to_wdev(ndev) +-#else +-#define ndev_to_cfgdev(ndev) (ndev) +-#endif /* WL_CFG80211_P2P_DEV_IF */ +- +-#if defined(WL_CFG80211_P2P_DEV_IF) +-#define scan_req_match(wl) (((wl) && (wl->scan_request) && \ +- (wl->scan_request->wdev == wl->p2p_wdev)) ? true : false) +-#elif defined(WL_ENABLE_P2P_IF) +-#define scan_req_match(wl) (((wl) && (wl->scan_request) && \ +- (wl->scan_request->dev == wl->p2p_net)) ? true : false) +-#else +-#define scan_req_match(wl) (((wl) && p2p_is_on(wl) && p2p_scan(wl)) ? \ +- true : false) +-#endif /* WL_CFG80211_P2P_DEV_IF */ +- + #define wl_to_sr(w) (w->scan_req_int) + #if defined(STATIC_WL_PRIV_STRUCT) + #define wl_to_ie(w) (w->ie) +@@ -847,7 +795,7 @@ wl_get_netinfo_by_netdev(struct wl_priv + (wl_set_status_by_netdev(wl, WL_STATUS_ ## stat, ndev, 1)) + #define wl_clr_drv_status(wl, stat, ndev) \ + (wl_set_status_by_netdev(wl, WL_STATUS_ ## stat, ndev, 2)) +-#define wl_clr_drv_status_all(wl, stat) \ ++#define wl_clr_drv_status_all(wl, stat) \ + (wl_set_status_all(wl, WL_STATUS_ ## stat, 2)) + #define wl_chg_drv_status(wl, stat, ndev) \ + (wl_set_status_by_netdev(wl, WL_STATUS_ ## stat, ndev, 4)) +@@ -895,30 +843,18 @@ extern s32 wl_cfg80211_set_p2p_ps(struct + extern int wl_cfg80211_hang(struct net_device *dev, u16 reason); + extern s32 wl_mode_to_nl80211_iftype(s32 mode); + int wl_cfg80211_do_driver_init(struct net_device *net); +-void wl_cfg80211_enable_trace(bool set, u32 level); ++void wl_cfg80211_enable_trace(u32 level); + extern s32 wl_update_wiphybands(struct wl_priv *wl, bool notify); + extern s32 wl_cfg80211_if_is_group_owner(void); + extern chanspec_t wl_ch_host_to_driver(u16 channel); + extern s32 wl_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add); +-extern void wl_stop_wait_next_action_frame(struct wl_priv *wl); ++extern void wl_stop_wait_next_action_frame(struct wl_priv *wl, struct net_device *ndev); ++extern s32 wl_cfg80211_set_band(struct net_device *ndev, int band); + extern int wl_cfg80211_update_power_mode(struct net_device *dev); ++#if defined(DHCP_SCAN_SUPPRESS) ++extern int wl_cfg80211_scan_suppress(struct net_device *dev, int suppress); ++#endif /* OEM_ANDROID */ + extern void wl_cfg80211_add_to_eventbuffer(wl_eventmsg_buf_t *ev, u16 event, bool set); + extern s32 wl_cfg80211_apply_eventbuffer(struct net_device *ndev, + struct wl_priv *wl, wl_eventmsg_buf_t *ev); +-extern void get_primary_mac(struct wl_priv *wl, struct ether_addr *mac); +-#define SCAN_BUF_CNT 2 +-#define SCAN_BUF_NEXT 1 +-#define wl_escan_set_sync_id(a, b) ((a) = htod16(0x1234)) +-#define wl_escan_get_buf(a, b) ((wl_scan_results_t *) (a)->escan_info.escan_buf) +-#define wl_escan_check_sync_id(a, b, c) 0 +-#define wl_escan_print_sync_id(a, b, c) +-#define wl_escan_increment_sync_id(a, b) +-#define wl_escan_init_sync_id(a) +-extern void wl_cfg80211_ibss_vsie_set_buffer(vndr_ie_setbuf_t *ibss_vsie, int ibss_vsie_len); +-extern s32 wl_cfg80211_ibss_vsie_delete(struct net_device *dev); +- +-/* Action frame specific functions */ +-extern u8 wl_get_action_category(void *frame, u32 frame_len); +-extern int wl_get_public_action(void *frame, u32 frame_len, u8 *ret_action); +- + #endif /* _wl_cfg80211_h_ */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/wl_cfgp2p.c linux-sunxi-new/drivers/net/wireless/bcmdhd/wl_cfgp2p.c +--- linux-sunxi/drivers/net/wireless/bcmdhd/wl_cfgp2p.c 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/wl_cfgp2p.c 2014-02-15 00:43:44.795014136 +0100 +@@ -1,7 +1,7 @@ + /* + * Linux cfgp2p driver + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -21,7 +21,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: wl_cfgp2p.c 419821 2013-08-22 21:43:26Z $ ++ * $Id: wl_cfgp2p.c 372668 2012-12-04 14:07:12Z $ + * + */ + #include +@@ -53,24 +53,22 @@ static bool + wl_cfgp2p_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, const u8 *oui, u32 oui_len, u8 type); + + static u32 +-wl_cfgp2p_vndr_ie(struct wl_priv *wl, u8 *iebuf, s32 pktflag, ++wl_cfgp2p_vndr_ie(struct wl_priv *wl, u8 *iebuf, s32 bssidx, s32 pktflag, + s8 *oui, s32 ie_id, s8 *data, s32 datalen, const s8* add_del_cmd); +-static s32 wl_cfgp2p_cancel_listen(struct wl_priv *wl, struct net_device *ndev, +- struct wireless_dev *wdev, bool notify); + +-#if defined(WL_ENABLE_P2P_IF) + static int wl_cfgp2p_start_xmit(struct sk_buff *skb, struct net_device *ndev); + static int wl_cfgp2p_do_ioctl(struct net_device *net, struct ifreq *ifr, int cmd); + static int wl_cfgp2p_if_open(struct net_device *net); + static int wl_cfgp2p_if_stop(struct net_device *net); ++static s32 wl_cfgp2p_cancel_listen(struct wl_priv *wl, struct net_device *ndev, ++ bool notify); + + static const struct net_device_ops wl_cfgp2p_if_ops = { +- .ndo_open = wl_cfgp2p_if_open, +- .ndo_stop = wl_cfgp2p_if_stop, +- .ndo_do_ioctl = wl_cfgp2p_do_ioctl, +- .ndo_start_xmit = wl_cfgp2p_start_xmit, ++ .ndo_open = wl_cfgp2p_if_open, ++ .ndo_stop = wl_cfgp2p_if_stop, ++ .ndo_do_ioctl = wl_cfgp2p_do_ioctl, ++ .ndo_start_xmit = wl_cfgp2p_start_xmit, + }; +-#endif /* WL_ENABLE_P2P_IF */ + + bool wl_cfgp2p_is_pub_action(void *frame, u32 frame_len) + { +@@ -111,6 +109,12 @@ bool wl_cfgp2p_is_p2p_action(void *frame + return false; + } + ++/* ++* Currently Action frame just pass to P2P interface regardless real dst. ++* but GAS Action can be used for Hotspot2.0 as well ++* Need to distingush that it's for P2P or HS20 ++*/ ++#ifdef WL11U + #define GAS_RESP_LEN 2 + #define DOUBLE_TLV_BODY_OFF 4 + #define GAS_RESP_OFFSET 4 +@@ -142,6 +146,7 @@ bool wl_cfgp2p_find_gas_subtype(u8 subty + + return false; + } ++#endif /* WL11U */ + + bool wl_cfgp2p_is_gas_action(void *frame, u32 frame_len) + { +@@ -152,16 +157,12 @@ bool wl_cfgp2p_is_gas_action(void *frame + return false; + + sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)frame; +- if (frame_len < (sizeof(wifi_p2psd_gas_pub_act_frame_t) - 1)) ++ if (frame_len < sizeof(wifi_p2psd_gas_pub_act_frame_t) - 1) + return false; + if (sd_act_frm->category != P2PSD_ACTION_CATEGORY) + return false; + + #ifdef WL11U +- /* XXX Hotspot2.0 STA mode can receive only response +- * SoftAP mode cannot run Hotspot2.0 compliant Ap because +- * Hotspot2.0 support only Enterprise mode +- */ + if (sd_act_frm->action == P2PSD_ACTION_ID_GAS_IRESP) + return wl_cfgp2p_find_gas_subtype(P2PSD_GAS_OUI_SUBTYPE, + (u8 *)sd_act_frm->query_data + GAS_RESP_OFFSET, +@@ -184,9 +185,9 @@ bool wl_cfgp2p_is_gas_action(void *frame + return true; + else + return false; +-#endif /* WL11U */ ++#endif /* WLC11U */ + } +-void wl_cfgp2p_print_actframe(bool tx, void *frame, u32 frame_len, u32 channel) ++void wl_cfgp2p_print_actframe(bool tx, void *frame, u32 frame_len) + { + wifi_p2p_pub_act_frame_t *pact_frm; + wifi_p2p_action_frame_t *act_frm; +@@ -198,44 +199,44 @@ void wl_cfgp2p_print_actframe(bool tx, v + pact_frm = (wifi_p2p_pub_act_frame_t *)frame; + switch (pact_frm->subtype) { + case P2P_PAF_GON_REQ: +- CFGP2P_ACTION(("%s P2P Group Owner Negotiation Req Frame," +- " channel=%d\n", (tx)? "TX": "RX", channel)); ++ CFGP2P_ACTION(("%s P2P Group Owner Negotiation Req Frame\n", ++ (tx)? "TX": "RX")); + break; + case P2P_PAF_GON_RSP: +- CFGP2P_ACTION(("%s P2P Group Owner Negotiation Rsp Frame," +- " channel=%d\n", (tx)? "TX": "RX", channel)); ++ CFGP2P_ACTION(("%s P2P Group Owner Negotiation Rsp Frame\n", ++ (tx)? "TX": "RX")); + break; + case P2P_PAF_GON_CONF: +- CFGP2P_ACTION(("%s P2P Group Owner Negotiation Confirm Frame," +- " channel=%d\n", (tx)? "TX": "RX", channel)); ++ CFGP2P_ACTION(("%s P2P Group Owner Negotiation Confirm Frame\n", ++ (tx)? "TX": "RX")); + break; + case P2P_PAF_INVITE_REQ: +- CFGP2P_ACTION(("%s P2P Invitation Request Frame," +- " channel=%d\n", (tx)? "TX": "RX", channel)); ++ CFGP2P_ACTION(("%s P2P Invitation Request Frame\n", ++ (tx)? "TX": "RX")); + break; + case P2P_PAF_INVITE_RSP: +- CFGP2P_ACTION(("%s P2P Invitation Response Frame," +- " channel=%d\n", (tx)? "TX": "RX", channel)); ++ CFGP2P_ACTION(("%s P2P Invitation Response Frame\n", ++ (tx)? "TX": "RX")); + break; + case P2P_PAF_DEVDIS_REQ: +- CFGP2P_ACTION(("%s P2P Device Discoverability Request Frame," +- " channel=%d\n", (tx)? "TX": "RX", channel)); ++ CFGP2P_ACTION(("%s P2P Device Discoverability Request Frame\n", ++ (tx)? "TX": "RX")); + break; + case P2P_PAF_DEVDIS_RSP: +- CFGP2P_ACTION(("%s P2P Device Discoverability Response Frame," +- " channel=%d\n", (tx)? "TX": "RX", channel)); ++ CFGP2P_ACTION(("%s P2P Device Discoverability Response Frame\n", ++ (tx)? "TX": "RX")); + break; + case P2P_PAF_PROVDIS_REQ: +- CFGP2P_ACTION(("%s P2P Provision Discovery Request Frame," +- " channel=%d\n", (tx)? "TX": "RX", channel)); ++ CFGP2P_ACTION(("%s P2P Provision Discovery Request Frame\n", ++ (tx)? "TX": "RX")); + break; + case P2P_PAF_PROVDIS_RSP: +- CFGP2P_ACTION(("%s P2P Provision Discovery Response Frame," +- " channel=%d\n", (tx)? "TX": "RX", channel)); ++ CFGP2P_ACTION(("%s P2P Provision Discovery Response Frame\n", ++ (tx)? "TX": "RX")); + break; + default: +- CFGP2P_ACTION(("%s Unknown P2P Public Action Frame," +- " channel=%d\n", (tx)? "TX": "RX", channel)); ++ CFGP2P_ACTION(("%s Unknown P2P Public Action Frame\n", ++ (tx)? "TX": "RX")); + + } + +@@ -243,48 +244,48 @@ void wl_cfgp2p_print_actframe(bool tx, v + act_frm = (wifi_p2p_action_frame_t *)frame; + switch (act_frm->subtype) { + case P2P_AF_NOTICE_OF_ABSENCE: +- CFGP2P_ACTION(("%s P2P Notice of Absence Frame," +- " channel=%d\n", (tx)? "TX": "RX", channel)); ++ CFGP2P_ACTION(("%s P2P Notice of Absence Frame\n", ++ (tx)? "TX": "RX")); + break; + case P2P_AF_PRESENCE_REQ: +- CFGP2P_ACTION(("%s P2P Presence Request Frame," +- " channel=%d\n", (tx)? "TX": "RX", channel)); ++ CFGP2P_ACTION(("%s P2P Presence Request Frame\n", ++ (tx)? "TX": "RX")); + break; + case P2P_AF_PRESENCE_RSP: +- CFGP2P_ACTION(("%s P2P Presence Response Frame," +- " channel=%d\n", (tx)? "TX": "RX", channel)); ++ CFGP2P_ACTION(("%s P2P Presence Response Frame\n", ++ (tx)? "TX": "RX")); + break; + case P2P_AF_GO_DISC_REQ: +- CFGP2P_ACTION(("%s P2P Discoverability Request Frame," +- " channel=%d\n", (tx)? "TX": "RX", channel)); ++ CFGP2P_ACTION(("%s P2P Discoverability Request Frame\n", ++ (tx)? "TX": "RX")); + break; + default: +- CFGP2P_ACTION(("%s Unknown P2P Action Frame," +- " channel=%d\n", (tx)? "TX": "RX", channel)); ++ CFGP2P_ACTION(("%s Unknown P2P Action Frame\n", ++ (tx)? "TX": "RX")); + } + + } else if (wl_cfgp2p_is_gas_action(frame, frame_len)) { + sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)frame; + switch (sd_act_frm->action) { + case P2PSD_ACTION_ID_GAS_IREQ: +- CFGP2P_ACTION(("%s P2P GAS Initial Request," +- " channel=%d\n", (tx)? "TX" : "RX", channel)); ++ CFGP2P_ACTION(("%s P2P GAS Initial Request\n", ++ (tx)? "TX" : "RX")); + break; + case P2PSD_ACTION_ID_GAS_IRESP: +- CFGP2P_ACTION(("%s P2P GAS Initial Response," +- " channel=%d\n", (tx)? "TX" : "RX", channel)); ++ CFGP2P_ACTION(("%s P2P GAS Initial Response\n", ++ (tx)? "TX" : "RX")); + break; + case P2PSD_ACTION_ID_GAS_CREQ: +- CFGP2P_ACTION(("%s P2P GAS Comback Request," +- " channel=%d\n", (tx)? "TX" : "RX", channel)); ++ CFGP2P_ACTION(("%s P2P GAS Comback Request\n", ++ (tx)? "TX" : "RX")); + break; + case P2PSD_ACTION_ID_GAS_CRESP: +- CFGP2P_ACTION(("%s P2P GAS Comback Response," +- " channel=%d\n", (tx)? "TX" : "RX", channel)); ++ CFGP2P_ACTION(("%s P2P GAS Comback Response\n", ++ (tx)? "TX" : "RX")); + break; + default: +- CFGP2P_ACTION(("%s Unknown P2P GAS Frame," +- " channel=%d\n", (tx)? "TX" : "RX", channel)); ++ CFGP2P_ACTION(("%s Unknown P2P GAS Frame\n", ++ (tx)? "TX" : "RX")); + } + + +@@ -359,11 +360,7 @@ wl_cfgp2p_set_firm_p2p(struct wl_priv *w + s32 ret = BCME_OK; + s32 val = 0; + /* Do we have to check whether APSTA is enabled or not ? */ +- ret = wldev_iovar_getint(ndev, "apsta", &val); +- if (ret < 0) { +- CFGP2P_ERR(("get apsta error %d\n", ret)); +- return ret; +- } ++ wldev_iovar_getint(ndev, "apsta", &val); + if (val == 0) { + val = 1; + ret = wldev_ioctl(ndev, WLC_DOWN, &val, sizeof(s32), true); +@@ -431,7 +428,7 @@ wl_cfgp2p_ifadd(struct wl_priv *wl, stru + + /* Disable a P2P BSS. + * Parameters: +- * @mac : MAC address of the BSS to disable ++ * @mac : MAC address of the BSS to create + * Returns 0 if success. + */ + s32 +@@ -452,7 +449,7 @@ wl_cfgp2p_ifdisable(struct wl_priv *wl, + + /* Delete a P2P BSS. + * Parameters: +- * @mac : MAC address of the BSS to delete ++ * @mac : MAC address of the BSS to create + * Returns 0 if success. + */ + s32 +@@ -569,12 +566,12 @@ wl_cfgp2p_set_p2p_mode(struct wl_priv *w + struct net_device *dev; + CFGP2P_DBG(("enter\n")); + +- if (unlikely(bssidx == WL_INVALID)) { ++ if (unlikely(bssidx == WL_INVALID || bssidx >= P2PAPI_BSSCFG_MAX)) { + CFGP2P_ERR((" %d index out of range\n", bssidx)); + return -1; + } + +- dev = wl_cfgp2p_find_ndev(wl, bssidx); ++ dev = wl_to_p2p_bss_ndev(wl, bssidx); + if (unlikely(dev == NULL)) { + CFGP2P_ERR(("bssidx %d is not assigned\n", bssidx)); + return BCME_NOTFOUND; +@@ -698,14 +695,8 @@ wl_cfgp2p_enable_discovery(struct wl_pri + const u8 *ie, u32 ie_len) + { + s32 ret = BCME_OK; +- s32 bssidx; +- +- if (wl_to_prmry_ndev(wl) == dev) { +- bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE); +- } else if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { +- WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); +- return BCME_ERROR; +- } ++ s32 bssidx = (wl_to_prmry_ndev(wl) == dev) ? ++ wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE) : wl_cfgp2p_find_idx(wl, dev); + if (wl_get_p2p_status(wl, DISCOVERY_ON)) { + CFGP2P_INFO((" DISCOVERY is already initialized, we have nothing to do\n")); + goto set_ie; +@@ -781,8 +772,7 @@ exit: + s32 + wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active, + u32 num_chans, u16 *channels, +- s32 search_state, u16 action, u32 bssidx, struct ether_addr *tx_dst_addr, +- p2p_scan_purpose_t p2p_scan_purpose) ++ s32 search_state, u16 action, u32 bssidx) + { + s32 ret = BCME_OK; + s32 memsize; +@@ -809,7 +799,7 @@ wl_cfgp2p_escan(struct wl_priv *wl, stru + memsize = sizeof(wl_p2p_scan_t) + eparams_size; + memblk = scanparambuf; + if (memsize > sizeof(scanparambuf)) { +- CFGP2P_ERR((" scanpar buf too small (%u > %zu)\n", ++ CFGP2P_ERR((" scanpar buf too small (%u > %u)\n", + memsize, sizeof(scanparambuf))); + return -1; + } +@@ -821,9 +811,8 @@ wl_cfgp2p_escan(struct wl_priv *wl, stru + * because dongle use P2P WILDCARD internally by default + */ + wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_SEARCH, 0, 0, bssidx); +- /* use null ssid */ +- ssid.SSID_len = 0; +- memset(&ssid.SSID, 0, sizeof(ssid.SSID)); ++ ssid.SSID_len = htod32(0); ++ + } else if (search_state == WL_P2P_DISC_ST_SCAN) { + /* SCAN STATE 802.11 SCAN + * WFD Supplicant has p2p_find command with (type=progressive, type= full) +@@ -831,12 +820,12 @@ wl_cfgp2p_escan(struct wl_priv *wl, stru + * we have to set ssid to P2P WILDCARD because + * we just do broadcast scan unless setting SSID + */ ++ strncpy(ssid.SSID, WL_P2P_WILDCARD_SSID, sizeof(ssid.SSID) - 1); ++ ssid.SSID[sizeof(ssid.SSID) - 1] = 0; ++ ssid.SSID_len = htod32(WL_P2P_WILDCARD_SSID_LEN); + wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_SCAN, 0, 0, bssidx); +- /* use wild card ssid */ +- ssid.SSID_len = WL_P2P_WILDCARD_SSID_LEN; +- memset(&ssid.SSID, 0, sizeof(ssid.SSID)); +- memcpy(&ssid.SSID, WL_P2P_WILDCARD_SSID, WL_P2P_WILDCARD_SSID_LEN); +- } else { ++ } ++ else { + CFGP2P_ERR((" invalid search state %d\n", search_state)); + return -1; + } +@@ -853,42 +842,32 @@ wl_cfgp2p_escan(struct wl_priv *wl, stru + else + eparams->params.scan_type = DOT11_SCANTYPE_PASSIVE; + +- if (tx_dst_addr == NULL) +- memcpy(&eparams->params.bssid, ðer_bcast, ETHER_ADDR_LEN); +- else +- memcpy(&eparams->params.bssid, tx_dst_addr, ETHER_ADDR_LEN); +- ++ memcpy(&eparams->params.bssid, ðer_bcast, ETHER_ADDR_LEN); + if (ssid.SSID_len) + memcpy(&eparams->params.ssid, &ssid, sizeof(wlc_ssid_t)); + + eparams->params.home_time = htod32(P2PAPI_SCAN_HOME_TIME_MS); + +- switch (p2p_scan_purpose) { +- case P2P_SCAN_SOCIAL_CHANNEL: +- eparams->params.active_time = htod32(P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS); +- break; +- case P2P_SCAN_AFX_PEER_NORMAL: +- case P2P_SCAN_AFX_PEER_REDUCED: +- eparams->params.active_time = htod32(P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS); +- break; +- case P2P_SCAN_CONNECT_TRY: +- eparams->params.active_time = htod32(WL_SCAN_CONNECT_DWELL_TIME_MS); +- break; +- default : +- if (wl_get_drv_status_all(wl, CONNECTED)) +- eparams->params.active_time = -1; +- else +- eparams->params.active_time = htod32(P2PAPI_SCAN_DWELL_TIME_MS); +- break; +- } +- +- if (p2p_scan_purpose == P2P_SCAN_CONNECT_TRY) ++ /* SOCIAL_CHAN_CNT + 1 takes care of the Progressive scan supported by ++ * the supplicant ++ */ ++ if ((num_chans == SOCIAL_CHAN_CNT) || (num_chans == SOCIAL_CHAN_CNT + 1)) ++ eparams->params.active_time = htod32(P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS); ++ else if (num_chans == AF_PEER_SEARCH_CNT) ++ eparams->params.active_time = htod32(P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS); ++ else if (wl_get_drv_status_all(wl, CONNECTED)) ++ eparams->params.active_time = -1; ++ else ++ eparams->params.active_time = htod32(P2PAPI_SCAN_DWELL_TIME_MS); ++ eparams->params.nprobes = htod32((eparams->params.active_time / ++ P2PAPI_SCAN_NPROBS_TIME_MS)); ++ ++ /* Override scan params to find a peer for a connection */ ++ if (num_chans == 1) { ++ eparams->params.active_time = htod32(WL_SCAN_CONNECT_DWELL_TIME_MS); + eparams->params.nprobes = htod32(eparams->params.active_time / + WL_SCAN_JOIN_PROBE_INTERVAL_MS); +- else +- eparams->params.nprobes = htod32((eparams->params.active_time / +- P2PAPI_SCAN_NPROBS_TIME_MS)); +- ++ } + + if (eparams->params.nprobes <= 0) + eparams->params.nprobes = 1; +@@ -903,7 +882,7 @@ wl_cfgp2p_escan(struct wl_priv *wl, stru + } + eparams->version = htod32(ESCAN_REQ_VERSION); + eparams->action = htod16(action); +- wl_escan_set_sync_id(eparams->sync_id, wl); ++ eparams->sync_id = htod16(0x1234); + CFGP2P_INFO(("SCAN CHANNELS : ")); + + for (i = 0; i < num_chans; i++) { +@@ -929,17 +908,16 @@ wl_cfgp2p_escan(struct wl_priv *wl, stru + */ + s32 + wl_cfgp2p_act_frm_search(struct wl_priv *wl, struct net_device *ndev, +- s32 bssidx, s32 channel, struct ether_addr *tx_dst_addr) ++ s32 bssidx, s32 channel) + { + s32 ret = 0; + u32 chan_cnt = 0; + u16 *default_chan_list = NULL; +- p2p_scan_purpose_t p2p_scan_purpose = P2P_SCAN_AFX_PEER_NORMAL; + if (!p2p_is_on(wl) || ndev == NULL || bssidx == WL_INVALID) + return -BCME_ERROR; +- CFGP2P_DBG((" Enter\n")); +- if (bssidx == wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_PRIMARY)) +- bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE); ++ CFGP2P_ERR((" Enter\n")); ++ if (bssidx == P2PAPI_BSSCFG_PRIMARY) ++ bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE); + if (channel) + chan_cnt = AF_PEER_SEARCH_CNT; + else +@@ -961,10 +939,9 @@ wl_cfgp2p_act_frm_search(struct wl_priv + default_chan_list[1] = SOCIAL_CHAN_2; + default_chan_list[2] = SOCIAL_CHAN_3; + } +- + ret = wl_cfgp2p_escan(wl, ndev, true, chan_cnt, + default_chan_list, WL_P2P_DISC_ST_SEARCH, +- WL_SCAN_ACTION_START, bssidx, tx_dst_addr, p2p_scan_purpose); ++ WL_SCAN_ACTION_START, bssidx); + kfree(default_chan_list); + exit: + return ret; +@@ -980,9 +957,7 @@ exit: + #define wl_cfgp2p_is_p2p_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \ + (const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_P2P) + /* Check whether the given IE looks like WFA WFDisplay IE. */ +-#ifndef WFA_OUI_TYPE_WFD + #define WFA_OUI_TYPE_WFD 0x0a /* WiFi Display OUI TYPE */ +-#endif + #define wl_cfgp2p_is_wfd_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \ + (const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_WFD) + +@@ -1071,50 +1046,45 @@ wl_cfgp2p_set_management_ie(struct wl_pr + struct parsed_vndr_ies new_vndr_ies; + s32 i; + u8 *ptr; +- s32 type = -1; + s32 remained_buf_len; ++ + #define IE_TYPE(type, bsstype) (wl_to_p2p_bss_saved_ie(wl, bsstype).p2p_ ## type ## _ie) + #define IE_TYPE_LEN(type, bsstype) (wl_to_p2p_bss_saved_ie(wl, bsstype).p2p_ ## type ## _ie_len) + memset(g_mgmt_ie_buf, 0, sizeof(g_mgmt_ie_buf)); + curr_ie_buf = g_mgmt_ie_buf; + CFGP2P_DBG((" bssidx %d, pktflag : 0x%02X\n", bssidx, pktflag)); + if (wl->p2p != NULL) { +- if (wl_cfgp2p_find_type(wl, bssidx, &type)) { +- CFGP2P_ERR(("cannot find type from bssidx : %d\n", bssidx)); +- return BCME_ERROR; +- } +- + switch (pktflag) { + case VNDR_IE_PRBREQ_FLAG : +- mgmt_ie_buf = IE_TYPE(probe_req, type); +- mgmt_ie_len = &IE_TYPE_LEN(probe_req, type); +- mgmt_ie_buf_len = sizeof(IE_TYPE(probe_req, type)); ++ mgmt_ie_buf = IE_TYPE(probe_req, bssidx); ++ mgmt_ie_len = &IE_TYPE_LEN(probe_req, bssidx); ++ mgmt_ie_buf_len = sizeof(IE_TYPE(probe_req, bssidx)); + break; + case VNDR_IE_PRBRSP_FLAG : +- mgmt_ie_buf = IE_TYPE(probe_res, type); +- mgmt_ie_len = &IE_TYPE_LEN(probe_res, type); +- mgmt_ie_buf_len = sizeof(IE_TYPE(probe_res, type)); ++ mgmt_ie_buf = IE_TYPE(probe_res, bssidx); ++ mgmt_ie_len = &IE_TYPE_LEN(probe_res, bssidx); ++ mgmt_ie_buf_len = sizeof(IE_TYPE(probe_res, bssidx)); + break; + case VNDR_IE_ASSOCREQ_FLAG : +- mgmt_ie_buf = IE_TYPE(assoc_req, type); +- mgmt_ie_len = &IE_TYPE_LEN(assoc_req, type); +- mgmt_ie_buf_len = sizeof(IE_TYPE(assoc_req, type)); ++ mgmt_ie_buf = IE_TYPE(assoc_req, bssidx); ++ mgmt_ie_len = &IE_TYPE_LEN(assoc_req, bssidx); ++ mgmt_ie_buf_len = sizeof(IE_TYPE(assoc_req, bssidx)); + break; + case VNDR_IE_ASSOCRSP_FLAG : +- mgmt_ie_buf = IE_TYPE(assoc_res, type); +- mgmt_ie_len = &IE_TYPE_LEN(assoc_res, type); +- mgmt_ie_buf_len = sizeof(IE_TYPE(assoc_res, type)); ++ mgmt_ie_buf = IE_TYPE(assoc_res, bssidx); ++ mgmt_ie_len = &IE_TYPE_LEN(assoc_res, bssidx); ++ mgmt_ie_buf_len = sizeof(IE_TYPE(assoc_res, bssidx)); + break; + case VNDR_IE_BEACON_FLAG : +- mgmt_ie_buf = IE_TYPE(beacon, type); +- mgmt_ie_len = &IE_TYPE_LEN(beacon, type); +- mgmt_ie_buf_len = sizeof(IE_TYPE(beacon, type)); ++ mgmt_ie_buf = IE_TYPE(beacon, bssidx); ++ mgmt_ie_len = &IE_TYPE_LEN(beacon, bssidx); ++ mgmt_ie_buf_len = sizeof(IE_TYPE(beacon, bssidx)); + break; + default: + mgmt_ie_buf = NULL; + mgmt_ie_len = NULL; + CFGP2P_ERR(("not suitable type\n")); +- return BCME_ERROR; ++ return -1; + } + } else if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_AP) { + switch (pktflag) { +@@ -1132,7 +1102,7 @@ wl_cfgp2p_set_management_ie(struct wl_pr + mgmt_ie_buf = NULL; + mgmt_ie_len = NULL; + CFGP2P_ERR(("not suitable type\n")); +- return BCME_ERROR; ++ return -1; + } + bssidx = 0; + } else if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_BSS) { +@@ -1151,12 +1121,12 @@ wl_cfgp2p_set_management_ie(struct wl_pr + mgmt_ie_buf = NULL; + mgmt_ie_len = NULL; + CFGP2P_ERR(("not suitable type\n")); +- return BCME_ERROR; ++ return -1; + } + bssidx = 0; + } else { + CFGP2P_ERR(("not suitable type\n")); +- return BCME_ERROR; ++ return -1; + } + + if (vndr_ie_len > mgmt_ie_buf_len) { +@@ -1202,7 +1172,7 @@ wl_cfgp2p_set_management_ie(struct wl_pr + vndrie_info->vndrie.oui[2])); + + del_add_ie_buf_len = wl_cfgp2p_vndr_ie(wl, curr_ie_buf, +- pktflag, vndrie_info->vndrie.oui, ++ bssidx, pktflag, vndrie_info->vndrie.oui, + vndrie_info->vndrie.id, + vndrie_info->ie_ptr + VNDR_IE_FIXED_LEN, + vndrie_info->ie_len - VNDR_IE_FIXED_LEN, +@@ -1232,7 +1202,7 @@ wl_cfgp2p_set_management_ie(struct wl_pr + vndrie_info->vndrie.oui[2])); + + del_add_ie_buf_len = wl_cfgp2p_vndr_ie(wl, curr_ie_buf, +- pktflag, vndrie_info->vndrie.oui, ++ bssidx, pktflag, vndrie_info->vndrie.oui, + vndrie_info->vndrie.id, + vndrie_info->ie_ptr + VNDR_IE_FIXED_LEN, + vndrie_info->ie_len - VNDR_IE_FIXED_LEN, +@@ -1283,11 +1253,9 @@ exit: + s32 + wl_cfgp2p_clear_management_ie(struct wl_priv *wl, s32 bssidx) + { +- + s32 vndrie_flag[] = {VNDR_IE_BEACON_FLAG, VNDR_IE_PRBRSP_FLAG, VNDR_IE_ASSOCRSP_FLAG, + VNDR_IE_PRBREQ_FLAG, VNDR_IE_ASSOCREQ_FLAG}; + s32 index = -1; +- s32 type = -1; + struct net_device *ndev = wl_cfgp2p_find_ndev(wl, bssidx); + #define INIT_IE(IE_TYPE, BSS_TYPE) \ + do { \ +@@ -1300,20 +1268,15 @@ wl_cfgp2p_clear_management_ie(struct wl_ + CFGP2P_ERR(("invalid %s\n", (bssidx < 0) ? "bssidx" : "ndev")); + return BCME_BADARG; + } +- +- if (wl_cfgp2p_find_type(wl, bssidx, &type)) { +- CFGP2P_ERR(("invalid argument\n")); +- return BCME_BADARG; +- } + for (index = 0; index < ARRAYSIZE(vndrie_flag); index++) { + /* clean up vndr ies in dongle */ + wl_cfgp2p_set_management_ie(wl, ndev, bssidx, vndrie_flag[index], NULL, 0); + } +- INIT_IE(probe_req, type); +- INIT_IE(probe_res, type); +- INIT_IE(assoc_req, type); +- INIT_IE(assoc_res, type); +- INIT_IE(beacon, type); ++ INIT_IE(probe_req, bssidx); ++ INIT_IE(probe_res, bssidx); ++ INIT_IE(assoc_req, bssidx); ++ INIT_IE(assoc_res, bssidx); ++ INIT_IE(beacon, bssidx); + return BCME_OK; + } + +@@ -1395,7 +1358,7 @@ wl_cfgp2p_find_wfdie(u8 *parse, u32 len) + return NULL; + } + static u32 +-wl_cfgp2p_vndr_ie(struct wl_priv *wl, u8 *iebuf, s32 pktflag, ++wl_cfgp2p_vndr_ie(struct wl_priv *wl, u8 *iebuf, s32 bssidx, s32 pktflag, + s8 *oui, s32 ie_id, s8 *data, s32 datalen, const s8* add_del_cmd) + { + vndr_ie_setbuf_t hdr; /* aligned temporary vndr_ie buffer header */ +@@ -1452,32 +1415,33 @@ wl_cfgp2p_vndr_ie(struct wl_priv *wl, u8 + * Parameters: + * @wl : wl_private data + * @ndev : net device to search bssidx +- * @bssidx : output arg to store bssidx of the bsscfg of firmware. +- * Returns error ++ * Returns bssidx for ndev + */ + s32 +-wl_cfgp2p_find_idx(struct wl_priv *wl, struct net_device *ndev, s32 *bssidx) ++wl_cfgp2p_find_idx(struct wl_priv *wl, struct net_device *ndev) + { + u32 i; +- if (ndev == NULL || bssidx == NULL) { +- CFGP2P_ERR((" argument is invalid\n")); +- return BCME_BADARG; ++ s32 index = -1; ++ ++ if (ndev == NULL) { ++ CFGP2P_ERR((" ndev is NULL\n")); ++ goto exit; + } + if (!wl->p2p_supported) { +- *bssidx = P2PAPI_BSSCFG_PRIMARY; +- return BCME_OK; ++ return P2PAPI_BSSCFG_PRIMARY; + } +- /* we cannot find the bssidx of DISCOVERY BSS +- * because the ndev is same with ndev of PRIMARY BSS. +- */ + for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) { + if (ndev == wl_to_p2p_bss_ndev(wl, i)) { +- *bssidx = wl_to_p2p_bss_bssidx(wl, i); +- return BCME_OK; ++ index = wl_to_p2p_bss_bssidx(wl, i); ++ break; + } + } +- return BCME_BADARG; ++ if (index == -1) ++ return P2PAPI_BSSCFG_PRIMARY; ++exit: ++ return index; + } ++ + struct net_device * + wl_cfgp2p_find_ndev(struct wl_priv *wl, s32 bssidx) + { +@@ -1498,52 +1462,24 @@ wl_cfgp2p_find_ndev(struct wl_priv *wl, + exit: + return ndev; + } +-/* +- * Search the driver array idx based on bssidx argument +- * Parameters: +- * @wl : wl_private data +- * @bssidx : bssidx which indicate bsscfg->idx of firmware. +- * @type : output arg to store array idx of p2p->bss. +- * Returns error +- */ +- +-s32 +-wl_cfgp2p_find_type(struct wl_priv *wl, s32 bssidx, s32 *type) +-{ +- u32 i; +- if (bssidx < 0 || type == NULL) { +- CFGP2P_ERR((" argument is invalid\n")); +- goto exit; +- } +- +- for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) { +- if (bssidx == wl_to_p2p_bss_bssidx(wl, i)) { +- *type = i; +- return BCME_OK; +- } +- } +- +-exit: +- return BCME_BADARG; +-} + + /* + * Callback function for WLC_E_P2P_DISC_LISTEN_COMPLETE + */ + s32 +-wl_cfgp2p_listen_complete(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev, +- const wl_event_msg_t *e, void *data) ++wl_cfgp2p_listen_complete(struct wl_priv *wl, struct net_device *ndev, ++ const wl_event_msg_t *e, void *data) + { + s32 ret = BCME_OK; +- struct net_device *ndev = NULL; +- ++ struct net_device *netdev; + if (!wl || !wl->p2p) + return BCME_ERROR; +- ++ if (wl->p2p_net == ndev) { ++ netdev = wl_to_prmry_ndev(wl); ++ } else { ++ netdev = ndev; ++ } + CFGP2P_DBG((" Enter\n")); +- +- ndev = cfgdev_to_wlc_ndev(cfgdev, wl); +- + if (wl_get_p2p_status(wl, LISTEN_EXPIRED) == 0) { + wl_set_p2p_status(wl, LISTEN_EXPIRED); + if (timer_pending(&wl->p2p->listen_timer)) { +@@ -1557,12 +1493,12 @@ wl_cfgp2p_listen_complete(struct wl_priv + } + #ifdef WL_CFG80211_SYNC_GON + else if (wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM_LISTEN)) { +- wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM_LISTEN, ndev); ++ wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM_LISTEN, netdev); + WL_DBG(("Listen DONE and wake up wait_next_af !!(%d)\n", + jiffies_to_msecs(jiffies - wl->af_tx_sent_jiffies))); + + if (wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM)) +- wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM, ndev); ++ wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM, netdev); + + complete(&wl->wait_next_af); + } +@@ -1575,18 +1511,13 @@ wl_cfgp2p_listen_complete(struct wl_priv + wl_get_drv_status_all(wl, FAKE_REMAINING_ON_CHANNEL)) { + #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */ + WL_DBG(("Listen DONE for ramain on channel expired\n")); +- wl_clr_drv_status(wl, REMAINING_ON_CHANNEL, ndev); ++ wl_clr_drv_status(wl, REMAINING_ON_CHANNEL, netdev); + #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST +- wl_clr_drv_status(wl, FAKE_REMAINING_ON_CHANNEL, ndev); ++ wl_clr_drv_status(wl, FAKE_REMAINING_ON_CHANNEL, netdev); + #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */ + if (ndev && (ndev->ieee80211_ptr != NULL)) { +-#if defined(WL_CFG80211_P2P_DEV_IF) +- cfg80211_remain_on_channel_expired(cfgdev, wl->last_roc_id, +- &wl->remain_on_chan, GFP_KERNEL); +-#else +- cfg80211_remain_on_channel_expired(cfgdev, wl->last_roc_id, ++ cfg80211_remain_on_channel_expired(ndev, wl->last_roc_id, + &wl->remain_on_chan, wl->remain_on_chan_type, GFP_KERNEL); +-#endif /* WL_CFG80211_P2P_DEV_IF */ + } + } + if (wl_add_remove_eventmsg(wl_to_prmry_ndev(wl), +@@ -1613,20 +1544,15 @@ wl_cfgp2p_listen_expired(unsigned long d + CFGP2P_DBG((" Enter\n")); + bzero(&msg, sizeof(wl_event_msg_t)); + msg.event_type = hton32(WLC_E_P2P_DISC_LISTEN_COMPLETE); +-#if defined(WL_ENABLE_P2P_IF) + wl_cfg80211_event(wl->p2p_net ? wl->p2p_net : + wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_DEVICE), &msg, NULL); +-#else +- wl_cfg80211_event(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_DEVICE), &msg, +- NULL); +-#endif /* WL_ENABLE_P2P_IF */ + } + /* + * Routine for cancelling the P2P LISTEN + */ + static s32 + wl_cfgp2p_cancel_listen(struct wl_priv *wl, struct net_device *ndev, +- struct wireless_dev *wdev, bool notify) ++ bool notify) + { + WL_DBG(("Enter \n")); + /* Irrespective of whether timer is running or not, reset +@@ -1636,13 +1562,9 @@ wl_cfgp2p_cancel_listen(struct wl_priv * + del_timer_sync(&wl->p2p->listen_timer); + if (notify) + if (ndev && ndev->ieee80211_ptr) { +-#if defined(WL_CFG80211_P2P_DEV_IF) +- cfg80211_remain_on_channel_expired(wdev, wl->last_roc_id, +- &wl->remain_on_chan, GFP_KERNEL); +-#else + cfg80211_remain_on_channel_expired(ndev, wl->last_roc_id, +- &wl->remain_on_chan, wl->remain_on_chan_type, GFP_KERNEL); +-#endif /* WL_CFG80211_P2P_DEV_IF */ ++ &wl->remain_on_chan, wl->remain_on_chan_type, ++ GFP_KERNEL); + } + } + return 0; +@@ -1746,35 +1668,31 @@ wl_cfgp2p_discover_enable_search(struct + * Callback function for WLC_E_ACTION_FRAME_COMPLETE, WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE + */ + s32 +-wl_cfgp2p_action_tx_complete(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev, ++wl_cfgp2p_action_tx_complete(struct wl_priv *wl, struct net_device *ndev, + const wl_event_msg_t *e, void *data) + { + s32 ret = BCME_OK; + u32 event_type = ntoh32(e->event_type); + u32 status = ntoh32(e->status); + CFGP2P_DBG((" Enter\n")); +- if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) { +- if (event_type == WLC_E_ACTION_FRAME_COMPLETE) { +- +- CFGP2P_INFO((" WLC_E_ACTION_FRAME_COMPLETE is received : %d\n", status)); +- if (status == WLC_E_STATUS_SUCCESS) { +- wl_set_p2p_status(wl, ACTION_TX_COMPLETED); +- CFGP2P_DBG(("WLC_E_ACTION_FRAME_COMPLETE : ACK\n")); +- } +- else { +- if (!wl_get_p2p_status(wl, ACTION_TX_COMPLETED)) { +- wl_set_p2p_status(wl, ACTION_TX_NOACK); +- CFGP2P_INFO(("WLC_E_ACTION_FRAME_COMPLETE : NO ACK\n")); +- wl_stop_wait_next_action_frame(wl); +- } +- } +- } else { +- CFGP2P_INFO((" WLC_E_ACTION_FRAME_OFFCHAN_COMPLETE is received," +- "status : %d\n", status)); ++ if (event_type == WLC_E_ACTION_FRAME_COMPLETE) { + +- if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) +- complete(&wl->send_af_done); ++ CFGP2P_INFO((" WLC_E_ACTION_FRAME_COMPLETE is received : %d\n", status)); ++ if (status == WLC_E_STATUS_SUCCESS) { ++ wl_set_p2p_status(wl, ACTION_TX_COMPLETED); ++ CFGP2P_DBG(("WLC_E_ACTION_FRAME_COMPLETE : ACK\n")); + } ++ else { ++ wl_set_p2p_status(wl, ACTION_TX_NOACK); ++ CFGP2P_INFO(("WLC_E_ACTION_FRAME_COMPLETE : NO ACK\n")); ++ wl_stop_wait_next_action_frame(wl, ndev); ++ } ++ } else { ++ CFGP2P_INFO((" WLC_E_ACTION_FRAME_OFFCHAN_COMPLETE is received," ++ "status : %d\n", status)); ++ ++ if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) ++ complete(&wl->send_af_done); + } + return ret; + } +@@ -1791,7 +1709,6 @@ wl_cfgp2p_tx_action_frame(struct wl_priv + wl_af_params_t *af_params, s32 bssidx) + { + s32 ret = BCME_OK; +- s32 evt_ret = BCME_OK; + s32 timeout = 0; + wl_eventmsg_buf_t buf; + +@@ -1806,9 +1723,10 @@ wl_cfgp2p_tx_action_frame(struct wl_priv + bzero(&buf, sizeof(wl_eventmsg_buf_t)); + wl_cfg80211_add_to_eventbuffer(&buf, WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE, true); + wl_cfg80211_add_to_eventbuffer(&buf, WLC_E_ACTION_FRAME_COMPLETE, true); +- if ((evt_ret = wl_cfg80211_apply_eventbuffer(wl_to_prmry_ndev(wl), wl, &buf)) < 0) +- return evt_ret; ++ if ((ret = wl_cfg80211_apply_eventbuffer(wl_to_prmry_ndev(wl), wl, &buf)) < 0) ++ return ret; + ++#define MAX_WAIT_TIME 2000 + if (bssidx == P2PAPI_BSSCFG_PRIMARY) + bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE); + +@@ -1825,10 +1743,9 @@ wl_cfgp2p_tx_action_frame(struct wl_priv + goto exit; + } + +- timeout = wait_for_completion_timeout(&wl->send_af_done, +- msecs_to_jiffies(af_params->dwell_time + WL_AF_TX_EXTRA_TIME_MAX)); ++ timeout = wait_for_completion_timeout(&wl->send_af_done, msecs_to_jiffies(MAX_WAIT_TIME)); + +- if (timeout >= 0 && wl_get_p2p_status(wl, ACTION_TX_COMPLETED)) { ++ if (timeout > 0 && wl_get_p2p_status(wl, ACTION_TX_COMPLETED)) { + CFGP2P_INFO(("tx action frame operation is completed\n")); + ret = BCME_OK; + } else { +@@ -1845,11 +1762,10 @@ exit: + bzero(&buf, sizeof(wl_eventmsg_buf_t)); + wl_cfg80211_add_to_eventbuffer(&buf, WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE, false); + wl_cfg80211_add_to_eventbuffer(&buf, WLC_E_ACTION_FRAME_COMPLETE, false); +- if ((evt_ret = wl_cfg80211_apply_eventbuffer(wl_to_prmry_ndev(wl), wl, &buf)) < 0) { ++ if ((ret = wl_cfg80211_apply_eventbuffer(wl_to_prmry_ndev(wl), wl, &buf)) < 0) + WL_ERR(("TX frame events revert back failed \n")); +- return evt_ret; +- } + ++#undef MAX_WAIT_TIME + return ret; + } + +@@ -2005,34 +1921,23 @@ wl_cfgp2p_supported(struct wl_priv *wl, + } + return p2p_supported; + } ++ + /* Cleanup P2P resources */ + s32 + wl_cfgp2p_down(struct wl_priv *wl) + { +- struct net_device *ndev = NULL; +- struct wireless_dev *wdev = NULL; + s32 i = 0, index = -1; +- +-#if defined(WL_CFG80211_P2P_DEV_IF) +- ndev = wl_to_prmry_ndev(wl); +- wdev = wl_to_p2p_wdev(wl); +-#elif defined(WL_ENABLE_P2P_IF) +- ndev = wl->p2p_net ? wl->p2p_net : wl_to_prmry_ndev(wl); +- wdev = ndev_to_wdev(ndev); +-#endif /* WL_CFG80211_P2P_DEV_IF */ +- +- wl_cfgp2p_cancel_listen(wl, ndev, wdev, TRUE); ++ wl_cfgp2p_cancel_listen(wl, ++ wl->p2p_net ? wl->p2p_net : wl_to_prmry_ndev(wl), TRUE); + for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) { + index = wl_to_p2p_bss_bssidx(wl, i); + if (index != WL_INVALID) + wl_cfgp2p_clear_management_ie(wl, index); + } +-#if defined(WL_CFG80211_P2P_DEV_IF) +- wl_cfgp2p_del_p2p_disc_if(wdev); +-#endif /* WL_CFG80211_P2P_DEV_IF */ + wl_cfgp2p_deinit_priv(wl); + return 0; + } ++ + s32 + wl_cfgp2p_set_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf, int len) + { +@@ -2175,7 +2080,7 @@ wl_cfgp2p_set_p2p_ps(struct wl_priv *wl, + } + + if ((legacy_ps != -1) && ((legacy_ps == PM_MAX) || (legacy_ps == PM_OFF))) { +-#if defined(SUPPORT_PM2_ONLY) ++#if !defined(SUPPORT_PM2_ONLY) + if (legacy_ps == PM_MAX) + legacy_ps = PM_FAST; + #endif /* SUPPORT_PM2_ONLY */ +@@ -2250,47 +2155,20 @@ wl_cfgp2p_retreive_p2pattrib(void *buf, + } + + #define P2P_GROUP_CAPAB_GO_BIT 0x01 +- +-u8* +-wl_cfgp2p_find_attrib_in_all_p2p_Ies(u8 *parse, u32 len, u32 attrib) +-{ +- bcm_tlv_t *ie; +- u8* pAttrib; +- +- CFGP2P_INFO(("Starting parsing parse %p attrib %d remaining len %d ", parse, attrib, len)); +- while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) { +- if (wl_cfgp2p_is_p2p_ie((uint8*)ie, &parse, &len) == TRUE) { +- /* Have the P2p ie. Now check for attribute */ +- if ((pAttrib = wl_cfgp2p_retreive_p2pattrib(parse, attrib)) != NULL) { +- CFGP2P_INFO(("P2P attribute %d was found at parse %p", +- attrib, parse)); +- return pAttrib; +- } +- else { +- parse += (ie->len + TLV_HDR_LEN); +- len -= (ie->len + TLV_HDR_LEN); +- CFGP2P_INFO(("P2P Attribute %d not found Moving parse" +- " to %p len to %d", attrib, parse, len)); +- } +- } +- else { +- /* It was not p2p IE. parse will get updated automatically to next TLV */ +- CFGP2P_INFO(("IT was NOT P2P IE parse %p len %d", parse, len)); +- } +- } +- CFGP2P_ERR(("P2P attribute %d was NOT found", attrib)); +- return NULL; +-} +- + u8 * + wl_cfgp2p_retreive_p2p_dev_addr(wl_bss_info_t *bi, u32 bi_length) + { ++ wifi_p2p_ie_t * p2p_ie = NULL; + u8 *capability = NULL; + bool p2p_go = 0; + u8 *ptr = NULL; + +- if ((capability = wl_cfgp2p_find_attrib_in_all_p2p_Ies(((u8 *) bi) + bi->ie_offset, +- bi->ie_length, P2P_SEID_P2P_INFO)) == NULL) { ++ if (!(p2p_ie = wl_cfgp2p_find_p2pie(((u8 *) bi) + bi->ie_offset, bi->ie_length))) { ++ WL_ERR(("P2P IE not found")); ++ return NULL; ++ } ++ ++ if (!(capability = wl_cfgp2p_retreive_p2pattrib(p2p_ie, P2P_SEID_P2P_INFO))) { + WL_ERR(("P2P Capability attribute not found")); + return NULL; + } +@@ -2302,13 +2180,11 @@ wl_cfgp2p_retreive_p2p_dev_addr(wl_bss_i + } + + /* In probe responses, DEVICE INFO attribute will be present */ +- if (!(ptr = wl_cfgp2p_find_attrib_in_all_p2p_Ies(((u8 *) bi) + bi->ie_offset, +- bi->ie_length, P2P_SEID_DEV_INFO))) { ++ if (!(ptr = wl_cfgp2p_retreive_p2pattrib(p2p_ie, P2P_SEID_DEV_INFO))) { + /* If DEVICE_INFO is not found, this might be a beacon frame. + * check for DEVICE_ID in the beacon frame. + */ +- ptr = wl_cfgp2p_find_attrib_in_all_p2p_Ies(((u8 *) bi) + bi->ie_offset, +- bi->ie_length, P2P_SEID_DEV_ID); ++ ptr = wl_cfgp2p_retreive_p2pattrib(p2p_ie, P2P_SEID_DEV_ID); + } + + if (!ptr) +@@ -2330,7 +2206,6 @@ struct ethtool_ops cfgp2p_ethtool_ops = + }; + #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */ + +-#if defined(WL_ENABLE_P2P_IF) + s32 + wl_cfgp2p_register_ndev(struct wl_priv *wl) + { +@@ -2427,7 +2302,6 @@ wl_cfgp2p_unregister_ndev(struct wl_priv + } + static int wl_cfgp2p_start_xmit(struct sk_buff *skb, struct net_device *ndev) + { +- + if (skb) + { + CFGP2P_DBG(("(%s) is not used for data operations.Droping the packet.\n", +@@ -2469,7 +2343,6 @@ static int wl_cfgp2p_if_open(struct net_ + if (!wdev || !wl || !wl->p2p) + return -EINVAL; + WL_TRACE(("Enter\n")); +-#if !defined(WL_IFACE_COMB_NUM_CHANNELS) + /* If suppose F/W download (ifconfig wlan0 up) hasn't been done by now, + * do it here. This will make sure that in concurrent mode, supplicant + * is not dependent on a particular order of interface initialization. +@@ -2478,7 +2351,6 @@ static int wl_cfgp2p_if_open(struct net_ + */ + wdev->wiphy->interface_modes |= (BIT(NL80211_IFTYPE_P2P_CLIENT) + | BIT(NL80211_IFTYPE_P2P_GO)); +-#endif /* !WL_IFACE_COMB_NUM_CHANNELS */ + wl_cfg80211_do_driver_init(net); + + return 0; +@@ -2507,11 +2379,9 @@ static int wl_cfgp2p_if_stop(struct net_ + spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); + if (clear_flag) + wl_clr_drv_status(wl, SCANNING, net); +-#if !defined(WL_IFACE_COMB_NUM_CHANNELS) + wdev->wiphy->interface_modes = (wdev->wiphy->interface_modes) + & (~(BIT(NL80211_IFTYPE_P2P_CLIENT)| + BIT(NL80211_IFTYPE_P2P_GO))); +-#endif /* !WL_IFACE_COMB_NUM_CHANNELS */ + return 0; + } + +@@ -2519,143 +2389,3 @@ bool wl_cfgp2p_is_ifops(const struct net + { + return (if_ops == &wl_cfgp2p_if_ops); + } +-#endif /* WL_ENABLE_P2P_IF */ +- +-#if defined(WL_CFG80211_P2P_DEV_IF) +-struct wireless_dev * +-wl_cfgp2p_add_p2p_disc_if(void) +-{ +- extern struct wl_priv *wlcfg_drv_priv; +- struct wl_priv *wl = wlcfg_drv_priv; +- struct wireless_dev *wdev = NULL; +- struct ether_addr primary_mac; +- +- if (!wl) +- return NULL; +- +- WL_TRACE(("Enter\n")); +- +- if (wl->p2p_wdev) { +- CFGP2P_ERR(("p2p_wdev defined already.\n")); +- return NULL; +- } +- +- wdev = kzalloc(sizeof(*wdev), GFP_KERNEL); +- if (unlikely(!wdev)) { +- WL_ERR(("Could not allocate wireless device\n")); +- return NULL; +- } +- +- memset(&primary_mac, 0, sizeof(primary_mac)); +- get_primary_mac(wl, &primary_mac); +- wl_cfgp2p_generate_bss_mac(&primary_mac, +- &wl->p2p->dev_addr, &wl->p2p->int_addr); +- +- wdev->wiphy = wl->wdev->wiphy; +- wdev->iftype = NL80211_IFTYPE_P2P_DEVICE; +- memcpy(wdev->address, &wl->p2p->dev_addr, ETHER_ADDR_LEN); +- +- /* store p2p wdev ptr for further reference. */ +- wl->p2p_wdev = wdev; +- +- CFGP2P_ERR(("P2P interface registered\n")); +- +- return wdev; +-} +- +-int +-wl_cfgp2p_start_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev) +-{ +- int ret = 0; +- extern struct wl_priv *wlcfg_drv_priv; +- struct wl_priv *wl = wlcfg_drv_priv; +- +- if (!wl) +- return -EINVAL; +- +- WL_TRACE(("Enter\n")); +- +- ret = wl_cfgp2p_set_firm_p2p(wl); +- if (unlikely(ret < 0)) { +- CFGP2P_ERR(("Set P2P in firmware failed, ret=%d\n", ret)); +- goto exit; +- } +- +- ret = wl_cfgp2p_enable_discovery(wl, wl_to_prmry_ndev(wl), NULL, 0); +- if (unlikely(ret < 0)) { +- CFGP2P_ERR(("P2P enable discovery failed, ret=%d\n", ret)); +- goto exit; +- } +- +- p2p_on(wl) = true; +- +- CFGP2P_DBG(("P2P interface started\n")); +- +-exit: +- return ret; +-} +- +-void +-wl_cfgp2p_stop_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev) +-{ +- int ret = 0; +- int clear_flag = 0; +- unsigned long flags = 0; +- struct net_device *ndev = NULL; +- extern struct wl_priv *wlcfg_drv_priv; +- struct wl_priv *wl = wlcfg_drv_priv; +- +- if (!wl || !wdev) +- return; +- +- WL_TRACE(("Enter\n")); +- +- ndev = wdev_to_wlc_ndev(wdev, wl); +- +- spin_lock_irqsave(&wl->cfgdrv_lock, flags); +- if (wl->scan_request && wl->scan_request->wdev == wdev) { +- cfg80211_scan_done(wl->scan_request, true); +- wl->scan_request = NULL; +- clear_flag = 1; +- } +- spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); +- +- if (clear_flag) +- wl_clr_drv_status(wl, SCANNING, ndev); +- +- ret = wl_cfgp2p_disable_discovery(wl); +- if (unlikely(ret < 0)) { +- CFGP2P_ERR(("P2P disable discovery failed, ret=%d\n", ret)); +- goto exit; +- } +- +- p2p_on(wl) = false; +- +- CFGP2P_DBG(("P2P interface stopped\n")); +- +-exit: +- return; +-} +- +-int +-wl_cfgp2p_del_p2p_disc_if(struct wireless_dev *wdev) +-{ +- extern struct wl_priv *wlcfg_drv_priv; +- struct wl_priv *wl = wlcfg_drv_priv; +- +- if (!wdev) +- return -EINVAL; +- +- WL_TRACE(("Enter\n")); +- +- cfg80211_unregister_wdev(wdev); +- +- kfree(wdev); +- +- wl->p2p_wdev = NULL; +- +- CFGP2P_ERR(("P2P interface unregistered\n")); +- +- return 0; +-} +-#endif /* WL_CFG80211_P2P_DEV_IF */ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/wl_cfgp2p.h linux-sunxi-new/drivers/net/wireless/bcmdhd/wl_cfgp2p.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/wl_cfgp2p.h 2014-01-27 01:30:30.100433249 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/wl_cfgp2p.h 2014-02-15 00:43:44.791014047 +0100 +@@ -1,7 +1,7 @@ + /* + * Linux cfgp2p driver + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -21,7 +21,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: wl_cfgp2p.h 415640 2013-07-31 02:43:28Z $ ++ * $Id: wl_cfgp2p.h 368091 2012-11-12 04:28:31Z $ + */ + #ifndef _wl_cfgp2p_h_ + #define _wl_cfgp2p_h_ +@@ -43,17 +43,6 @@ typedef enum { + P2PAPI_BSSCFG_MAX + } p2p_bsscfg_type_t; + +-typedef enum { +- P2P_SCAN_PURPOSE_MIN, +- P2P_SCAN_SOCIAL_CHANNEL, /* scan for social channel */ +- P2P_SCAN_AFX_PEER_NORMAL, /* scan for action frame search */ +- P2P_SCAN_AFX_PEER_REDUCED, /* scan for action frame search with short time */ +- P2P_SCAN_DURING_CONNECTED, /* scan during connected status */ +- P2P_SCAN_CONNECT_TRY, /* scan for connecting */ +- P2P_SCAN_NORMAL, /* scan during not-connected status */ +- P2P_SCAN_PURPOSE_MAX +-} p2p_scan_purpose_t; +- + /* vendor ies max buffer length for probe response or beacon */ + #define VNDR_IES_MAX_BUF_LEN 1400 + /* normal vendor ies buffer length */ +@@ -83,13 +72,12 @@ struct p2p_bss { + struct p2p_info { + bool on; /* p2p on/off switch */ + bool scan; +- int16 search_state; + bool vif_created; + s8 vir_ifname[IFNAMSIZ]; + unsigned long status; + struct ether_addr dev_addr; + struct ether_addr int_addr; +- struct p2p_bss bss[P2PAPI_BSSCFG_MAX]; ++ struct p2p_bss bss_idx[P2PAPI_BSSCFG_MAX]; + struct timer_list listen_timer; + wl_p2p_sched_t noa; + wl_p2p_ops_t ops; +@@ -127,11 +115,11 @@ enum wl_cfgp2p_status { + }; + + +-#define wl_to_p2p_bss_ndev(wl, type) ((wl)->p2p->bss[type].dev) +-#define wl_to_p2p_bss_bssidx(wl, type) ((wl)->p2p->bss[type].bssidx) +-#define wl_to_p2p_bss_saved_ie(wl, type) ((wl)->p2p->bss[type].saved_ie) +-#define wl_to_p2p_bss_private(wl, type) ((wl)->p2p->bss[type].private_data) +-#define wl_to_p2p_bss(wl, type) ((wl)->p2p->bss[type]) ++#define wl_to_p2p_bss_ndev(wl, type) ((wl)->p2p->bss_idx[type].dev) ++#define wl_to_p2p_bss_bssidx(wl, type) ((wl)->p2p->bss_idx[type].bssidx) ++#define wl_to_p2p_bss_saved_ie(wl, type) ((wl)->p2p->bss_idx[type].saved_ie) ++#define wl_to_p2p_bss_private(wl, type) ((wl)->p2p->bss_idx[type].private_data) ++#define wl_to_p2p_bss(wl, type) ((wl)->p2p->bss_idx[type]) + #define wl_get_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0 : test_bit(WLP2P_STATUS_ ## stat, \ + &(wl)->p2p->status)) + #define wl_set_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0 : set_bit(WLP2P_STATUS_ ## stat, \ +@@ -149,7 +137,6 @@ enum wl_cfgp2p_status { + + #define CFGP2P_ERROR_TEXT "CFGP2P-ERROR) " + +- + #define CFGP2P_ERR(args) \ + do { \ + if (wl_dbg_level & WL_DBG_ERR) { \ +@@ -167,7 +154,7 @@ enum wl_cfgp2p_status { + #define CFGP2P_DBG(args) \ + do { \ + if (wl_dbg_level & WL_DBG_DBG) { \ +- printk(KERN_DEBUG "CFGP2P-DEBUG) %s :", __func__); \ ++ printk(KERN_INFO "CFGP2P-DEBUG) %s :", __func__); \ + printk args; \ + } \ + } while (0) +@@ -175,7 +162,7 @@ enum wl_cfgp2p_status { + #define CFGP2P_ACTION(args) \ + do { \ + if (wl_dbg_level & WL_DBG_P2P_ACTION) { \ +- printk(KERN_DEBUG "CFGP2P-ACTION) %s :", __func__); \ ++ printk(KERN_INFO "CFGP2P-ACTION) %s :", __func__); \ + printk args; \ + } \ + } while (0) +@@ -187,27 +174,6 @@ enum wl_cfgp2p_status { + timer->data = (unsigned long) wl; \ + add_timer(timer); \ + } while (0); +- +-#if !defined(WL_CFG80211_P2P_DEV_IF) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) +-#define WL_CFG80211_P2P_DEV_IF +-#endif /* !WL_CFG80211_P2P_DEV_IF && (LINUX_VERSION >= VERSION(3, 8, 0)) */ +- +-#if defined(WL_ENABLE_P2P_IF) && (defined(WL_CFG80211_P2P_DEV_IF) || \ +- (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))) +-#error Disable 'WL_ENABLE_P2P_IF', if 'WL_CFG80211_P2P_DEV_IF' is enabled \ +- or kernel version is 3.8.0 or above +-#endif /* WL_ENABLE_P2P_IF && (WL_CFG80211_P2P_DEV_IF || (LINUX_VERSION >= VERSION(3, 8, 0))) */ +- +-#if !defined(WLP2P) && (defined(WL_ENABLE_P2P_IF) || defined(WL_CFG80211_P2P_DEV_IF)) +-#error WLP2P not defined +-#endif +- +-#if defined(WL_CFG80211_P2P_DEV_IF) +-#define bcm_struct_cfgdev struct wireless_dev +-#else +-#define bcm_struct_cfgdev struct net_device +-#endif /* WL_CFG80211_P2P_DEV_IF */ +- + extern void + wl_cfgp2p_listen_expired(unsigned long data); + extern bool +@@ -216,10 +182,8 @@ extern bool + wl_cfgp2p_is_p2p_action(void *frame, u32 frame_len); + extern bool + wl_cfgp2p_is_gas_action(void *frame, u32 frame_len); +-extern bool +-wl_cfgp2p_find_gas_subtype(u8 subtype, u8* data, u32 len); + extern void +-wl_cfgp2p_print_actframe(bool tx, void *frame, u32 frame_len, u32 channel); ++wl_cfgp2p_print_actframe(bool tx, void *frame, u32 frame_len); + extern s32 + wl_cfgp2p_init_priv(struct wl_priv *wl); + extern void +@@ -251,12 +215,11 @@ wl_cfgp2p_disable_discovery(struct wl_pr + extern s32 + wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active, u32 num_chans, + u16 *channels, +- s32 search_state, u16 action, u32 bssidx, struct ether_addr *tx_dst_addr, +- p2p_scan_purpose_t p2p_scan_purpose); ++ s32 search_state, u16 action, u32 bssidx); + + extern s32 + wl_cfgp2p_act_frm_search(struct wl_priv *wl, struct net_device *ndev, +- s32 bssidx, s32 channel, struct ether_addr *tx_dst_addr); ++ s32 bssidx, s32 channel); + + extern wpa_ie_fixed_t * + wl_cfgp2p_find_wpaie(u8 *parse, u32 len); +@@ -276,16 +239,14 @@ extern s32 + wl_cfgp2p_clear_management_ie(struct wl_priv *wl, s32 bssidx); + + extern s32 +-wl_cfgp2p_find_idx(struct wl_priv *wl, struct net_device *ndev, s32 *index); ++wl_cfgp2p_find_idx(struct wl_priv *wl, struct net_device *ndev); + extern struct net_device * + wl_cfgp2p_find_ndev(struct wl_priv *wl, s32 bssidx); +-extern s32 +-wl_cfgp2p_find_type(struct wl_priv *wl, s32 bssidx, s32 *type); + + + extern s32 +-wl_cfgp2p_listen_complete(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev, +- const wl_event_msg_t *e, void *data); ++wl_cfgp2p_listen_complete(struct wl_priv *wl, struct net_device *ndev, ++ const wl_event_msg_t *e, void *data); + extern s32 + wl_cfgp2p_discover_listen(struct wl_priv *wl, s32 channel, u32 duration_ms); + +@@ -293,9 +254,8 @@ extern s32 + wl_cfgp2p_discover_enable_search(struct wl_priv *wl, u8 enable); + + extern s32 +-wl_cfgp2p_action_tx_complete(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev, +- const wl_event_msg_t *e, void *data); +- ++wl_cfgp2p_action_tx_complete(struct wl_priv *wl, struct net_device *ndev, ++ const wl_event_msg_t *e, void *data); + extern s32 + wl_cfgp2p_tx_action_frame(struct wl_priv *wl, struct net_device *dev, + wl_af_params_t *af_params, s32 bssidx); +@@ -331,9 +291,6 @@ wl_cfgp2p_set_p2p_ps(struct wl_priv *wl, + extern u8 * + wl_cfgp2p_retreive_p2pattrib(void *buf, u8 element_id); + +-extern u8* +-wl_cfgp2p_find_attrib_in_all_p2p_Ies(u8 *parse, u32 len, u32 attrib); +- + extern u8 * + wl_cfgp2p_retreive_p2p_dev_addr(wl_bss_info_t *bi, u32 bi_length); + +@@ -346,20 +303,6 @@ wl_cfgp2p_unregister_ndev(struct wl_priv + extern bool + wl_cfgp2p_is_ifops(const struct net_device_ops *if_ops); + +-#if defined(WL_CFG80211_P2P_DEV_IF) +-extern struct wireless_dev * +-wl_cfgp2p_add_p2p_disc_if(void); +- +-extern int +-wl_cfgp2p_start_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev); +- +-extern void +-wl_cfgp2p_stop_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev); +- +-extern int +-wl_cfgp2p_del_p2p_disc_if(struct wireless_dev *wdev); +-#endif /* WL_CFG80211_P2P_DEV_IF */ +- + /* WiFi Direct */ + #define SOCIAL_CHAN_1 1 + #define SOCIAL_CHAN_2 6 +@@ -375,16 +318,20 @@ wl_cfgp2p_del_p2p_disc_if(struct wireles + #define WL_P2P_TEMP_CHAN 11 + + /* If the provision discovery is for JOIN operations, +- * or the device discoverablity frame is destined to GO + * then we need not do an internal scan to find GO. + */ +-#define IS_ACTPUB_WITHOUT_GROUP_ID(p2p_ie, len) \ ++#define IS_PROV_DISC_WITHOUT_GROUP_ID(p2p_ie, len) \ + (wl_cfgp2p_retreive_p2pattrib(p2p_ie, P2P_SEID_GROUP_ID) == NULL) + + #define IS_GAS_REQ(frame, len) (wl_cfgp2p_is_gas_action(frame, len) && \ + ((frame->action == P2PSD_ACTION_ID_GAS_IREQ) || \ + (frame->action == P2PSD_ACTION_ID_GAS_CREQ))) +- ++#define IS_P2P_PUB_ACT_REQ(frame, p2p_ie, len) \ ++ (wl_cfgp2p_is_pub_action(frame, len) && \ ++ ((frame->subtype == P2P_PAF_GON_REQ) || \ ++ (frame->subtype == P2P_PAF_INVITE_REQ) || \ ++ ((frame->subtype == P2P_PAF_PROVDIS_REQ) && \ ++ IS_PROV_DISC_WITHOUT_GROUP_ID(p2p_ie, len)))) + #define IS_P2P_PUB_ACT_RSP_SUBTYPE(subtype) ((subtype == P2P_PAF_GON_RSP) || \ + ((subtype == P2P_PAF_GON_CONF) || \ + (subtype == P2P_PAF_INVITE_RSP) || \ +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/wl_dbg.h linux-sunxi-new/drivers/net/wireless/bcmdhd/wl_dbg.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/wl_dbg.h 2014-01-27 01:30:30.107433391 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/wl_dbg.h 2014-02-15 00:43:44.795014136 +0100 +@@ -2,7 +2,7 @@ + * Minimal debug/trace/assert driver definitions for + * Broadcom 802.11 Networking Adapter. + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -22,7 +22,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: wl_dbg.h 376019 2012-12-21 01:00:06Z $ ++ * $Id: wl_dbg.h 326635 2012-04-10 03:15:29Z $ + */ + + +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/wldev_common.c linux-sunxi-new/drivers/net/wireless/bcmdhd/wldev_common.c +--- linux-sunxi/drivers/net/wireless/bcmdhd/wldev_common.c 2014-01-27 01:30:30.108433411 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/wldev_common.c 2014-02-15 00:43:44.795014136 +0100 +@@ -1,7 +1,7 @@ + /* + * Common function shared by Linux WEXT, cfg80211 and p2p drivers + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -32,12 +32,12 @@ + #include + #include + +-#define htod32(i) (i) +-#define htod16(i) (i) +-#define dtoh32(i) (i) +-#define dtoh16(i) (i) +-#define htodchanspec(i) (i) +-#define dtohchanspec(i) (i) ++#define htod32(i) i ++#define htod16(i) i ++#define dtoh32(i) i ++#define dtoh16(i) i ++#define htodchanspec(i) i ++#define dtohchanspec(i) i + + #define WLDEV_ERROR(args) \ + do { \ +@@ -109,7 +109,6 @@ s32 wldev_iovar_setbuf( + ret = wldev_ioctl(dev, WLC_SET_VAR, buf, iovar_len, TRUE); + else + ret = BCME_BUFTOOSHORT; +- + if (buf_sync) + mutex_unlock(buf_sync); + return ret; +@@ -336,7 +335,7 @@ int wldev_set_band( + } + + int wldev_set_country( +- struct net_device *dev, char *country_code, bool notify, bool user_enforced) ++ struct net_device *dev, char *country_code) + { + int error = -1; + wl_country_t cspec = {{0}, 0, {0}}; +@@ -346,26 +345,20 @@ int wldev_set_country( + if (!country_code) + return error; + +- bzero(&scbval, sizeof(scb_val_t)); +- error = wldev_iovar_getbuf(dev, "country", NULL, 0, &cspec, sizeof(cspec), NULL); +- if (error < 0) { ++ error = wldev_iovar_getbuf(dev, "country", &cspec, sizeof(cspec), ++ smbuf, sizeof(smbuf), NULL); ++ if (error < 0) + WLDEV_ERROR(("%s: get country failed = %d\n", __FUNCTION__, error)); +- return error; +- } + + if ((error < 0) || +- (strncmp(country_code, cspec.country_abbrev, WLC_CNTRY_BUF_SZ) != 0)) { +- +- if (user_enforced) { +- bzero(&scbval, sizeof(scb_val_t)); +- error = wldev_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t), true); +- if (error < 0) { +- WLDEV_ERROR(("%s: set country failed due to Disassoc error %d\n", +- __FUNCTION__, error)); +- return error; +- } ++ (strncmp(country_code, smbuf, WLC_CNTRY_BUF_SZ) != 0)) { ++ bzero(&scbval, sizeof(scb_val_t)); ++ error = wldev_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t), true); ++ if (error < 0) { ++ WLDEV_ERROR(("%s: set country failed due to Disassoc error %d\n", ++ __FUNCTION__, error)); ++ return error; + } +- + cspec.rev = -1; + memcpy(cspec.country_abbrev, country_code, WLC_CNTRY_BUF_SZ); + memcpy(cspec.ccode, country_code, WLC_CNTRY_BUF_SZ); +@@ -377,7 +370,7 @@ int wldev_set_country( + __FUNCTION__, country_code, cspec.ccode, cspec.rev)); + return error; + } +- dhd_bus_country_set(dev, &cspec, notify); ++ dhd_bus_country_set(dev, &cspec); + WLDEV_ERROR(("%s: set country for %s as %s rev %d\n", + __FUNCTION__, country_code, cspec.ccode, cspec.rev)); + } +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/wldev_common.h linux-sunxi-new/drivers/net/wireless/bcmdhd/wldev_common.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/wldev_common.h 2014-01-27 01:30:30.108433411 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/wldev_common.h 2014-02-15 00:43:44.795014136 +0100 +@@ -1,7 +1,7 @@ + /* + * Common function shared by Linux WEXT, cfg80211 and p2p drivers + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -84,10 +84,9 @@ s32 wldev_iovar_setint_bsscfg( + struct net_device *dev, s8 *iovar, s32 val, s32 bssidx); + + extern void get_customized_country_code(char *country_iso_code, wl_country_t *cspec); +-extern void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec, bool notify); ++extern void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec); + extern void dhd_bus_band_set(struct net_device *dev, uint band); +-extern int wldev_set_country(struct net_device *dev, char *country_code, bool notify, +- bool user_enforced); ++extern int wldev_set_country(struct net_device *dev, char *country_code); + extern int net_os_wake_lock(struct net_device *dev); + extern int net_os_wake_unlock(struct net_device *dev); + extern int net_os_wake_lock_timeout(struct net_device *dev); +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/wl_iw.c linux-sunxi-new/drivers/net/wireless/bcmdhd/wl_iw.c +--- linux-sunxi/drivers/net/wireless/bcmdhd/wl_iw.c 2014-01-27 01:30:30.100433249 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/wl_iw.c 2014-02-15 00:43:44.791014047 +0100 +@@ -1,7 +1,7 @@ + /* + * Linux Wireless Extensions support + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +@@ -21,7 +21,7 @@ + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * +- * $Id: wl_iw.c 396420 2013-04-12 06:55:45Z $ ++ * $Id: wl_iw.c 352251 2012-08-22 06:08:38Z $ + */ + + #if defined(USE_IW) +@@ -38,6 +38,7 @@ + #include + #include + ++ + typedef const struct si_pub si_t; + #include + +@@ -46,31 +47,6 @@ typedef const struct si_pub si_t; + #include + + +-/* Broadcom extensions to WEXT, linux upstream has obsoleted WEXT */ +-#ifndef IW_AUTH_KEY_MGMT_FT_802_1X +-#define IW_AUTH_KEY_MGMT_FT_802_1X 0x04 +-#endif +- +-#ifndef IW_AUTH_KEY_MGMT_FT_PSK +-#define IW_AUTH_KEY_MGMT_FT_PSK 0x08 +-#endif +- +-#ifndef IW_ENC_CAPA_FW_ROAM_ENABLE +-#define IW_ENC_CAPA_FW_ROAM_ENABLE 0x00000020 +-#endif +- +- +-/* FC9: wireless.h 2.6.25-14.fc9.i686 is missing these, even though WIRELESS_EXT is set to latest +- * version 22. +- */ +-#ifndef IW_ENCODE_ALG_PMK +-#define IW_ENCODE_ALG_PMK 4 +-#endif +-#ifndef IW_ENC_CAPA_4WAY_HANDSHAKE +-#define IW_ENC_CAPA_4WAY_HANDSHAKE 0x00000010 +-#endif +-/* End FC9. */ +- + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) + #include + #endif +@@ -82,7 +58,7 @@ tsk_ctl_t ap_eth_ctl; /* apsta AP netde + extern bool wl_iw_conn_status_str(uint32 event_type, uint32 status, + uint32 reason, char* stringBuf, uint buflen); + +-uint wl_msg_level = WL_ERROR_VAL; ++uint iw_msg_level = WL_ERROR_VAL; + + #define MAX_WLIW_IOCTL_LEN 1024 + +@@ -103,10 +79,7 @@ extern int dhd_wait_pend8021x(struct net + #endif /* WIRELESS_EXT < 19 */ + + +-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) +-#define DAEMONIZE(a) +-#elif ((LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) && \ +- (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))) ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) + #define DAEMONIZE(a) daemonize(a); \ + allow_signal(SIGKILL); \ + allow_signal(SIGTERM); +@@ -431,9 +404,6 @@ wl_iw_set_pm( + error = dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm)); + return error; + } +- +-#if WIRELESS_EXT > 17 +-#endif /* WIRELESS_EXT > 17 */ + #endif /* WIRELESS_EXT > 12 */ + + int +@@ -684,7 +654,6 @@ wl_iw_get_range( + {14, 29, 43, 58, 87, 116, 130, 144}, + {27, 54, 81, 108, 162, 216, 243, 270}, + {30, 60, 90, 120, 180, 240, 270, 300}}; +- int fbt_cap = 0; + + WL_TRACE(("%s: SIOCGIWRANGE\n", dev->name)); + +@@ -740,18 +709,15 @@ wl_iw_get_range( + range->num_bitrates = rateset.count; + for (i = 0; i < rateset.count && i < IW_MAX_BITRATES; i++) + range->bitrate[i] = (rateset.rates[i] & 0x7f) * 500000; /* convert to bps */ +- if ((error = dev_wlc_intvar_get(dev, "nmode", &nmode))) +- return error; ++ dev_wlc_intvar_get(dev, "nmode", &nmode); + if ((error = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &phytype, sizeof(phytype)))) + return error; ++ + if (nmode == 1 && ((phytype == WLC_PHY_TYPE_SSN) || (phytype == WLC_PHY_TYPE_LCN) || + (phytype == WLC_PHY_TYPE_LCN40))) { +- if ((error = dev_wlc_intvar_get(dev, "mimo_bw_cap", &bw_cap))) +- return error; +- if ((error = dev_wlc_intvar_get(dev, "sgi_tx", &sgi_tx))) +- return error; +- if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(channel_info_t)))) +- return error; ++ dev_wlc_intvar_get(dev, "mimo_bw_cap", &bw_cap); ++ dev_wlc_intvar_get(dev, "sgi_tx", &sgi_tx); ++ dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(channel_info_t)); + ci.hw_channel = dtoh32(ci.hw_channel); + + if (bw_cap == 0 || +@@ -769,7 +735,6 @@ wl_iw_get_range( + nrate_list2copy = 3; + } + range->num_bitrates += 8; +- ASSERT(range->num_bitrates < IW_MAX_BITRATES); + for (k = 0; i < range->num_bitrates; k++, i++) { + /* convert to bps */ + range->bitrate[i] = (nrate_list[nrate_list2copy][k]) * 500000; +@@ -840,19 +805,10 @@ wl_iw_get_range( + range->enc_capa |= IW_ENC_CAPA_CIPHER_TKIP; + range->enc_capa |= IW_ENC_CAPA_CIPHER_CCMP; + range->enc_capa |= IW_ENC_CAPA_WPA2; +- +- /* Determine driver FBT capability. */ +- if (dev_wlc_intvar_get(dev, "fbt_cap", &fbt_cap) == 0) { +- if (fbt_cap == WLC_FBT_CAP_DRV_4WAY_AND_REASSOC) { +- /* Tell the host (e.g. wpa_supplicant) to let driver do the handshake */ +- range->enc_capa |= IW_ENC_CAPA_4WAY_HANDSHAKE; +- } +- } +- +-#ifdef BCMFW_ROAM_ENABLE_WEXT +- /* Advertise firmware roam capability to the external supplicant */ +- range->enc_capa |= IW_ENC_CAPA_FW_ROAM_ENABLE; +-#endif /* BCMFW_ROAM_ENABLE_WEXT */ ++#if (defined(BCMSUP_PSK) && defined(WLFBT)) ++ /* Tell the host (e.g. wpa_supplicant) to let us do the handshake */ ++ range->enc_capa |= IW_ENC_CAPA_4WAY_HANDSHAKE; ++#endif /* (defined (BCMSUP_PSK) && defined(WLFBT)) */ + + /* Event capability (kernel) */ + IW_EVENT_CAPA_SET_KERNEL(range->event_capa); +@@ -1338,12 +1294,14 @@ wl_iw_handle_scanresults_ies(char **even + } + ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t); + ++#if defined(WLFBT) + if ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_MDIE_ID))) { + iwe.cmd = IWEVGENIE; + iwe.u.data.length = ie->len + 2; + event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie); + } + ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t); ++#endif /* WLFBT */ + + while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) { + /* look for WPS IE */ +@@ -2347,6 +2305,7 @@ wl_iw_set_encodeext( + return error; + } + } ++#if (defined(BCMSUP_PSK) && defined(WLFBT)) + /* This case is used to allow an external 802.1x supplicant + * to pass the PMK to the in-driver supplicant for use in + * the 4-way handshake. +@@ -2372,6 +2331,7 @@ wl_iw_set_encodeext( + if (error) + return error; + } ++#endif /* (defined (BCMSUP_PSK) && defined(WLFBT)) */ + + else { + if (iwe->key_len > sizeof(key.data)) +@@ -2573,8 +2533,7 @@ wl_iw_set_wpaauth( + break; + + case IW_AUTH_CIPHER_PAIRWISE: +- case IW_AUTH_CIPHER_GROUP: { +- int fbt_cap = 0; ++ case IW_AUTH_CIPHER_GROUP: + + if (paramid == IW_AUTH_CIPHER_PAIRWISE) { + iw->pwsec = paramval; +@@ -2611,44 +2570,33 @@ wl_iw_set_wpaauth( + + if ((error = dev_wlc_intvar_set(dev, "wsec", val))) + return error; +- +- /* Ensure in-dongle supplicant is turned on when FBT wants to do the 4-way +- * handshake. +- */ +- if (dev_wlc_intvar_get(dev, "fbt_cap", &fbt_cap) == 0) { +- if (fbt_cap == WLC_FBT_CAP_DRV_4WAY_AND_REASSOC) { +- if ((paramid == IW_AUTH_CIPHER_PAIRWISE) && (val & AES_ENABLED)) { +- if ((error = dev_wlc_intvar_set(dev, "sup_wpa", 1))) +- return error; +- } +- else if (val == 0) { +- if ((error = dev_wlc_intvar_set(dev, "sup_wpa", 0))) +- return error; +- } +- } ++#ifdef WLFBT ++ if ((paramid == IW_AUTH_CIPHER_PAIRWISE) && (val | AES_ENABLED)) { ++ if ((error = dev_wlc_intvar_set(dev, "sup_wpa", 1))) ++ return error; ++ } ++ else if (val == 0) { ++ if ((error = dev_wlc_intvar_set(dev, "sup_wpa", 0))) ++ return error; + } ++#endif /* WLFBT */ + break; +- } + + case IW_AUTH_KEY_MGMT: + if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val))) + return error; + + if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) { +- if (paramval & (IW_AUTH_KEY_MGMT_FT_PSK | IW_AUTH_KEY_MGMT_PSK)) ++ if (paramval & IW_AUTH_KEY_MGMT_PSK) + val = WPA_AUTH_PSK; + else + val = WPA_AUTH_UNSPECIFIED; +- if (paramval & (IW_AUTH_KEY_MGMT_FT_802_1X | IW_AUTH_KEY_MGMT_FT_PSK)) +- val |= WPA2_AUTH_FT; + } + else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) { +- if (paramval & (IW_AUTH_KEY_MGMT_FT_PSK | IW_AUTH_KEY_MGMT_PSK)) ++ if (paramval & IW_AUTH_KEY_MGMT_PSK) + val = WPA2_AUTH_PSK; + else + val = WPA2_AUTH_UNSPECIFIED; +- if (paramval & (IW_AUTH_KEY_MGMT_FT_802_1X | IW_AUTH_KEY_MGMT_FT_PSK)) +- val |= WPA2_AUTH_FT; + } + WL_TRACE(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val)); + if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val))) +@@ -2913,19 +2861,13 @@ static const iw_handler wl_iw_handler[] + enum { + WL_IW_SET_LEDDC = SIOCIWFIRSTPRIV, + WL_IW_SET_VLANMODE, +- WL_IW_SET_PM, +-#if WIRELESS_EXT > 17 +-#endif /* WIRELESS_EXT > 17 */ +- WL_IW_SET_LAST ++ WL_IW_SET_PM + }; + + static iw_handler wl_iw_priv_handler[] = { + wl_iw_set_leddc, + wl_iw_set_vlanmode, +- wl_iw_set_pm, +-#if WIRELESS_EXT > 17 +-#endif /* WIRELESS_EXT > 17 */ +- NULL ++ wl_iw_set_pm + }; + + static struct iw_priv_args wl_iw_priv_args[] = { +@@ -2946,10 +2888,7 @@ static struct iw_priv_args wl_iw_priv_ar + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, + "set_pm" +- }, +-#if WIRELESS_EXT > 17 +-#endif /* WIRELESS_EXT > 17 */ +- { 0, 0, 0, { 0 } } ++ } + }; + + const struct iw_handler_def wl_iw_handler_def = +@@ -3558,7 +3497,7 @@ static void wl_iw_send_scan_complete(isc + + memset(&wrqu, 0, sizeof(wrqu)); + +- /* wext expects to get no data for SIOCGIWSCAN Event */ ++ /* wext expects to get no data for SIOCGIWSCAN Event */ + wireless_send_event(iscan->dev, SIOCGIWSCAN, &wrqu, NULL); + } + +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/wl_iw.h linux-sunxi-new/drivers/net/wireless/bcmdhd/wl_iw.h +--- linux-sunxi/drivers/net/wireless/bcmdhd/wl_iw.h 2014-01-27 01:30:30.101433269 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/wl_iw.h 2014-02-15 00:43:44.792014069 +0100 +@@ -1,7 +1,7 @@ + /* + * Linux Wireless Extensions support + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you +diff -rupN linux-sunxi/drivers/net/wireless/bcmdhd/wl_linux_mon.c linux-sunxi-new/drivers/net/wireless/bcmdhd/wl_linux_mon.c +--- linux-sunxi/drivers/net/wireless/bcmdhd/wl_linux_mon.c 2014-01-27 01:30:30.109433432 +0100 ++++ linux-sunxi-new/drivers/net/wireless/bcmdhd/wl_linux_mon.c 2014-02-15 00:43:44.795014136 +0100 +@@ -1,7 +1,7 @@ + /* + * Broadcom Dongle Host Driver (DHD), Linux monitor network interface + * +- * Copyright (C) 1999-2013, Broadcom Corporation ++ * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you