From 8340edb2d8a24ee88bad3e230b77cbfedf81cff8 Mon Sep 17 00:00:00 2001 From: bnewbold Date: Tue, 21 Aug 2012 21:36:42 -0400 Subject: commit all files and directions See README and LICENSE. --- LICENSE | 7 + README | 169 +- config-3.4.0-1bauer2-kirkwood | 4176 ---------------- firmware/mrvl/helper_sd.bin | Bin 0 -> 2616 bytes firmware/mrvl/sd8688.bin | Bin 0 -> 297284 bytes firmware/mrvl/sd8688_ap.bin | Bin 0 -> 222572 bytes firmware/mrvl/sd8688_helper.bin | Bin 0 -> 2616 bytes libertas_uap/Makefile | 6 + libertas_uap/uap_debug.c | 261 + libertas_uap/uap_drv.h | 667 +++ libertas_uap/uap_fw.h | 359 ++ libertas_uap/uap_headers.h | 64 + libertas_uap/uap_main.c | 1815 +++++++ libertas_uap/uap_proc.c | 296 ++ libertas_uap/uap_sdio_mmc.c | 1428 ++++++ libertas_uap/uap_sdio_mmc.h | 136 + modprobe_libertas_uap.conf | 5 + uap8xxx.ko-3.2.9-kirkwood | Bin 0 -> 63316 bytes ...ell-Libertas-8688-SDIO-micro-AP-suppo-3.2.patch | 31 + with-linux-3.2/linux-3.0-SDIO-micro-AP.patch | 5111 ++++++++++++++++++++ .../linux-3.0.4-LIBERTAS-WEXT_PRIV.patch | 10 + with-linux-3.2/mvsdio-1-2.6.30.patch | 18 + with-linux-3.2/mvsdio-1-2.6.30.patch.larger | 32 + with-linux-3.2/mvsdio-2.patch | 35 + with-linux-3.2/mvsdio-3.patch | 13 + with-linux-3.2/phys-virt.diff | 14 + with-linux-3.2/series | 7 + ...ell-Libertas-8688-SDIO-micro-AP-suppo-3.2.patch | 31 - with-linux-3.4/dreamplug-3.4.0.patch | 107 - with-linux-3.4/linux-3.0-SDIO-micro-AP.patch | 5111 -------------------- .../linux-3.0.4-LIBERTAS-WEXT_PRIV.patch | 10 - with-linux-3.4/mvsdio-1-2.6.30.patch | 18 - with-linux-3.4/mvsdio-2.patch | 35 - with-linux-3.4/mvsdio-3.patch | 13 - with-linux-3.4/phys-virt.diff | 14 - with-linux-3.4/series | 8 - 36 files changed, 10436 insertions(+), 9571 deletions(-) create mode 100644 LICENSE delete mode 100644 config-3.4.0-1bauer2-kirkwood create mode 100755 firmware/mrvl/helper_sd.bin create mode 100755 firmware/mrvl/sd8688.bin create mode 100755 firmware/mrvl/sd8688_ap.bin create mode 100644 firmware/mrvl/sd8688_helper.bin create mode 100644 libertas_uap/Makefile create mode 100644 libertas_uap/uap_debug.c create mode 100644 libertas_uap/uap_drv.h create mode 100644 libertas_uap/uap_fw.h create mode 100644 libertas_uap/uap_headers.h create mode 100644 libertas_uap/uap_main.c create mode 100644 libertas_uap/uap_proc.c create mode 100644 libertas_uap/uap_sdio_mmc.c create mode 100644 libertas_uap/uap_sdio_mmc.h create mode 100644 modprobe_libertas_uap.conf create mode 100644 uap8xxx.ko-3.2.9-kirkwood create mode 100644 with-linux-3.2/0002-Driver-for-Marvell-Libertas-8688-SDIO-micro-AP-suppo-3.2.patch create mode 100644 with-linux-3.2/linux-3.0-SDIO-micro-AP.patch create mode 100644 with-linux-3.2/linux-3.0.4-LIBERTAS-WEXT_PRIV.patch create mode 100644 with-linux-3.2/mvsdio-1-2.6.30.patch create mode 100644 with-linux-3.2/mvsdio-1-2.6.30.patch.larger create mode 100644 with-linux-3.2/mvsdio-2.patch create mode 100644 with-linux-3.2/mvsdio-3.patch create mode 100644 with-linux-3.2/phys-virt.diff create mode 100644 with-linux-3.2/series delete mode 100644 with-linux-3.4/0002-Driver-for-Marvell-Libertas-8688-SDIO-micro-AP-suppo-3.2.patch delete mode 100644 with-linux-3.4/dreamplug-3.4.0.patch delete mode 100644 with-linux-3.4/linux-3.0-SDIO-micro-AP.patch delete mode 100644 with-linux-3.4/linux-3.0.4-LIBERTAS-WEXT_PRIV.patch delete mode 100644 with-linux-3.4/mvsdio-1-2.6.30.patch delete mode 100644 with-linux-3.4/mvsdio-2.patch delete mode 100644 with-linux-3.4/mvsdio-3.patch delete mode 100644 with-linux-3.4/phys-virt.diff delete mode 100644 with-linux-3.4/series diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..dca0a9b --- /dev/null +++ b/LICENSE @@ -0,0 +1,7 @@ +Frankly, all these files are a disappointing shit-show w/r/t attribution. + +The ./firmware/mrvl/ files were floating around on my DreamPlug and probably +came from + +The ./with-linux-3.2 patches are from http://www.xilka.com/, but have no +license and I don't know where they came from originally. Presumably GPL. diff --git a/README b/README index 2508718..a3351f6 100644 --- a/README +++ b/README @@ -1,52 +1,125 @@ -Patches in with-linux-3.4 -========================= +DreamPlug uap8xxx WiFi Access Point Kernel Module Patches for Linux 3.2 (wheezy) +================================================================================ -These patches were adapted to apply on Linux 3.4 from the ones found here: +This repository is forked from: + +https://github.com/bauermann/dreamplug + +The patches were "originally" grabbed from: http://sheeva.with-linux.com/sheeva/kernel/3/3.2/3.2.9/source/ -They assume the Dreamplug has the original u-boot shipped by Marvel. This -means that the kernel will expect it to report the Guruplug machine id -2659 instead of the official 3550, and it assumes u-boot doesn't provide -a flattened device tree. If your u-boot uses the Dreamplug id then you -can just remove the section about linux-3.4/arch/arm/tools/mach-types -from dreamplug-3.4.0.patch. If it also provides a flattened device tree, -then you don't need dreamplug-3.4.0.patch at all. - -Using the kernel patches ------------------------- - -Instructions based on freedom-maker's README [1]. - -To compile your own kernel, you can use config-3.4.0-1bauer2-kirkwood as basis. -Follow the following steps on the DreamPlug to compile a new kernel: - - 1. Get the kernel source and other needed packages. - # apt-get kernel-package lzma quilt - 2. Get the Linux 3.4 kernel. - # wget https://www.kernel.org/pub/linux/kernel/v3.0/linux-3.4.tar.bz2 - 2. Unpack it somewhere. - # tar xfj linux-3.4.tar.bz2 - 3. Apply the patches found in with-linux-3.4. - # cd linux-3.4 - # ln -s ../with-linux-3.4 patches - # quilt push -a - 4. Copy the config and compile. - # cp ../config-3.4.0-1bauer2-kirkwood .config - # make-kpkg clean - # make-kpkg --append-to-version -1bauer2-kirkwood --revision=3.4.0-1bauer2 --initrd --cross_compile=- kernel_image kernel_headers - 5. Install the packages. - # dpkg -i ../linux-{image,headers}-3.4.0-1bauer2-kirkwood_3.4.0-1bauer2_armel.deb - -After kernel is installed on device, hooks should be calling: - # flash-kernel 3.4.0-1bauer2-kirkwood - -After that you should get a uImage and uInitrd files under /boot. - -These packages should get a kernel up and running into DreamPlug device. -The compilation process takes 6 hours on the DreamPlug. You will need -approximately 1 GB of free space for the build (including the size of the -unpacked kernel source). - --- -[1] http://anonscm.debian.org/git/freedombox/freedom-maker.git/ +It looks like mvsdio-1-2.6.30.patch was edited in bauermann's version; i've +included the larger original for comparison. + +I made one more small but questionable tweak to get things to compile: +commenting out line 74 of libertas_uap/uap_debug.c. + +This repo is modeled on bauermann's 3.4 kernel patches, only "re-backported" to +contain older patches in a simple form for use compiling just the uap8xxx.ko +kernel module for the version 3.2.9 kernel that seems to be the stable release +version for debian wheezy. + +This is all a horrible short-term kludge. Preferably the libertas_uap/uap8xxx +code should get added to the kernel mainline, or at least be distributed in a +coherent fashion... but I am not that hero. + +Quick Binary Install +-------------------- + +If you have a dreamplug running the exact linux 3.2.9 kirkwood kernel that came +with debian wheezy or FreedomBox (as of Aug 22, 2012), you can just install the +uap8xxx.ko-3.2.9-kirkwood, firmware, and a modprobe file and you are good to +go... scp them to the device and then: + + # # as root + # mkdir /lib/modules/$(uname -r)/kernel/drivers/net/wireless/libertas_uap + # cp uap8xxx.ko-3.2.9-kirkwood /lib/modules/$(uname -r)/kernel/drivers/net/wireless/libertas_uap + # depmod -a + # cp -r firmware/mrvl /lib/firmware/mrvl + # cp modprobe_libertas_uap.conf /etc/modprobe.d/libertas_uap + # reboot + +Extracting kernel module source (on any machine) +------------------------------------------------ + +This explains the steps I took to extract out the uap8xxx ("libertas_uap") +module code. These are now in the libertas_uap folder in this repo, so you +don't need to repeate these steps. + +1. Get the kernel source and other needed packages. + # apt-get lzma quilt +2. Get the Linux 3.4 kernel. + # wget http://www.kernel.org/pub/linux/kernel/v3.x/linux-3.2.9.tar.xz +2. Unpack it somewhere. + # tar xvf linux-3.2.9.tar.bz2 +3. Apply the patches found in with-linux-3.2. + # cd linux-3.2.9 + # ln -s ../with-linux-3.2 patches + # quilt push -a +4. Copy out the module sources + # cp -r drivers/net/wireless/libertas_uap/ ../libertas_uap + +This source didn't compile for me as-is; I blindly commented out line 74 of +uap_debug.c, which is a horrible hack and might result in kernel crashes down +the line. + +Compiling uap8xxx.ko module (on DreamPlug) +------------------------------------------ + +These instructions based on an old mailing list post by Daniel Gillmor [1]. + +Generate a tarball of the libertas_uap files extracted above (or found in the +./libertas_uap folder of this repo): + + # tar -cf tar -cf libertas_uap.tar libertas_uap + # gzip libertas_uap.tar + +Copy that tarball over to a DreamPlug running a linux 3.2 kernel (only tested +with the debian wheezy 3.2.9 kernel) and install build requirements (slow!): + + # apt-get update + # apt-get install module-assistant vim screen linux-headers-kirkwood + +As any user, extract the source and build it: + + $ tar xzf libertas_uap.tar.gz + $ cd libertas_uap + $ make CONFIG_LIBERTAS_UAP=m -C /lib/modules/$(uname -r)/build M=$(pwd) + +This compiles pretty quickly for me, even on the DreamPlug. If that worked out, +install the results as root: + + # mkdir /lib/modules/$(uname -r)/kernel/drivers/net/wireless/libertas_uap + # cp uap8xxx.ko /lib/modules/$(uname -r)/kernel/drivers/net/wireless/libertas_uap + # depmod -a + +If you don't already have them installed, copy over the ./firmware/mrvl .bin +files and install as root: + + # cp -r firmware/mrvl /lib/firmware/mrvl + +To prevent block the libertas_sdio driver from glomming on to the hardware +before uap8xxx can get to it, blacklist the other drivers by adding this file +as /etc/modprobe.d/libertas_uap.conf (or just copy modprobe_libertas_uap.conf +from this repo): + + # blacklist competing modules for the same hardware + # used by libertas_uap (uap8xxx.ko) + blacklist libertas_sdio + blacklist libertas + +At this point I did a cold reboot (shutdown and disconnect power), though you +might be able to just modprobe following Dan's instructions: + + root@moo:~# ip link show uap0 + Device "uap0" does not exist. + root@moo:~# modprobe -v uap8xxx + insmod /lib/modules/2.6.32-5-kirkwood/kernel/drivers/net/wireless/libertas_uap/uap8xxx.ko + root@moo:~# ip link show uap0 + 4: uap0: mtu 1500 qdisc noop state DOWN qlen 1000 + link/ether 00:24:23:YY:WW:ZZ brd ff:ff:ff:ff:ff:ff + +Horray! + +[1] http://lists.debian.org/debian-arm/2010/05/msg00081.html diff --git a/config-3.4.0-1bauer2-kirkwood b/config-3.4.0-1bauer2-kirkwood deleted file mode 100644 index 6090489..0000000 --- a/config-3.4.0-1bauer2-kirkwood +++ /dev/null @@ -1,4176 +0,0 @@ -# -# Automatically generated file; DO NOT EDIT. -# Linux/arm 3.4.0-1bauer2-kirkwood Kernel Configuration -# -CONFIG_ARM=y -CONFIG_SYS_SUPPORTS_APM_EMULATION=y -CONFIG_GENERIC_GPIO=y -# CONFIG_ARCH_USES_GETTIMEOFFSET is not set -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_KTIME_SCALAR=y -CONFIG_HAVE_PROC_CPU=y -CONFIG_STACKTRACE_SUPPORT=y -CONFIG_HAVE_LATENCYTOP_SUPPORT=y -CONFIG_LOCKDEP_SUPPORT=y -CONFIG_TRACE_IRQFLAGS_SUPPORT=y -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_GENERIC_IRQ_PROBE=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y -CONFIG_GENERIC_HWEIGHT=y -CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_VECTORS_BASE=0xffff0000 -# CONFIG_ARM_PATCH_PHYS_VIRT is not set -CONFIG_NEED_MACH_IO_H=y -CONFIG_PHYS_OFFSET=0x0 -CONFIG_GENERIC_BUG=y -CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" -CONFIG_HAVE_IRQ_WORK=y -CONFIG_IRQ_WORK=y - -# -# General setup -# -CONFIG_EXPERIMENTAL=y -CONFIG_BROKEN_ON_SMP=y -CONFIG_INIT_ENV_ARG_LIMIT=32 -CONFIG_CROSS_COMPILE="" -CONFIG_LOCALVERSION="" -# 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 is not set -CONFIG_KERNEL_LZMA=y -# CONFIG_KERNEL_XZ is not set -# CONFIG_KERNEL_LZO is not set -CONFIG_DEFAULT_HOSTNAME="(none)" -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -CONFIG_SYSVIPC_SYSCTL=y -CONFIG_POSIX_MQUEUE=y -CONFIG_POSIX_MQUEUE_SYSCTL=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_BSD_PROCESS_ACCT_V3=y -CONFIG_FHANDLE=y -CONFIG_TASKSTATS=y -CONFIG_TASK_DELAY_ACCT=y -CONFIG_TASK_XACCT=y -CONFIG_TASK_IO_ACCOUNTING=y -CONFIG_AUDIT=y -CONFIG_AUDITSYSCALL=y -CONFIG_AUDIT_WATCH=y -CONFIG_AUDIT_TREE=y -# CONFIG_AUDIT_LOGINUID_IMMUTABLE is not set -CONFIG_HAVE_GENERIC_HARDIRQS=y - -# -# IRQ subsystem -# -CONFIG_GENERIC_HARDIRQS=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_IRQ_CHIP=y - -# -# RCU Subsystem -# -CONFIG_TINY_RCU=y -# CONFIG_PREEMPT_RCU is not set -# CONFIG_TREE_RCU_TRACE is not set -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -CONFIG_LOG_BUF_SHIFT=19 -CONFIG_CGROUPS=y -# CONFIG_CGROUP_DEBUG is not set -CONFIG_CGROUP_FREEZER=y -CONFIG_CGROUP_DEVICE=y -CONFIG_CPUSETS=y -CONFIG_PROC_PID_CPUSET=y -CONFIG_CGROUP_CPUACCT=y -CONFIG_RESOURCE_COUNTERS=y -CONFIG_CGROUP_MEM_RES_CTLR=y -CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y -# CONFIG_CGROUP_MEM_RES_CTLR_SWAP_ENABLED is not set -# CONFIG_CGROUP_MEM_RES_CTLR_KMEM is not set -# CONFIG_CGROUP_PERF is not set -CONFIG_CGROUP_SCHED=y -CONFIG_FAIR_GROUP_SCHED=y -# CONFIG_CFS_BANDWIDTH is not set -# CONFIG_RT_GROUP_SCHED is not set -CONFIG_BLK_CGROUP=y -# CONFIG_DEBUG_BLK_CGROUP is not set -# CONFIG_CHECKPOINT_RESTORE is not set -CONFIG_NAMESPACES=y -CONFIG_UTS_NS=y -CONFIG_IPC_NS=y -CONFIG_USER_NS=y -CONFIG_PID_NS=y -CONFIG_NET_NS=y -CONFIG_SCHED_AUTOGROUP=y -CONFIG_MM_OWNER=y -# CONFIG_SYSFS_DEPRECATED is not set -CONFIG_RELAY=y -CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_RD_GZIP=y -CONFIG_RD_BZIP2=y -CONFIG_RD_LZMA=y -CONFIG_RD_XZ=y -CONFIG_RD_LZO=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_SYSCTL=y -CONFIG_ANON_INODES=y -CONFIG_EXPERT=y -CONFIG_UID16=y -# CONFIG_SYSCTL_SYSCALL is not set -CONFIG_KALLSYMS=y -# CONFIG_KALLSYMS_ALL is not set -CONFIG_HOTPLUG=y -CONFIG_PRINTK=y -CONFIG_BUG=y -CONFIG_ELF_CORE=y -CONFIG_BASE_FULL=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_SIGNALFD=y -CONFIG_TIMERFD=y -CONFIG_EVENTFD=y -CONFIG_SHMEM=y -CONFIG_AIO=y -CONFIG_EMBEDDED=y -CONFIG_HAVE_PERF_EVENTS=y -CONFIG_PERF_USE_VMALLOC=y - -# -# Kernel Performance Events And Counters -# -CONFIG_PERF_EVENTS=y -# CONFIG_PERF_COUNTERS is not set -# CONFIG_DEBUG_PERF_USE_VMALLOC is not set -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_PCI_QUIRKS=y -CONFIG_SLUB_DEBUG=y -# CONFIG_COMPAT_BRK is not set -# CONFIG_SLAB is not set -CONFIG_SLUB=y -# CONFIG_SLOB is not set -# CONFIG_PROFILING is not set -CONFIG_TRACEPOINTS=y -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_REGS_AND_STACK_ACCESS_API=y -CONFIG_HAVE_DMA_API_DEBUG=y -CONFIG_HAVE_ARCH_JUMP_LABEL=y - -# -# GCOV-based kernel profiling -# -# CONFIG_GCOV_KERNEL is not set -CONFIG_HAVE_GENERIC_DMA_COHERENT=y -CONFIG_SLABINFO=y -CONFIG_RT_MUTEXES=y -CONFIG_BASE_SMALL=0 -CONFIG_MODULES=y -# CONFIG_MODULE_FORCE_LOAD is not set -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -# CONFIG_MODVERSIONS is not set -# CONFIG_MODULE_SRCVERSION_ALL is not set -CONFIG_BLOCK=y -CONFIG_LBDAF=y -CONFIG_BLK_DEV_BSG=y -CONFIG_BLK_DEV_BSGLIB=y -# CONFIG_BLK_DEV_INTEGRITY is not set -# CONFIG_BLK_DEV_THROTTLING is not set - -# -# Partition Types -# -CONFIG_PARTITION_ADVANCED=y -CONFIG_ACORN_PARTITION=y -# CONFIG_ACORN_PARTITION_CUMANA is not set -# CONFIG_ACORN_PARTITION_EESOX is not set -CONFIG_ACORN_PARTITION_ICS=y -# CONFIG_ACORN_PARTITION_ADFS is not set -# CONFIG_ACORN_PARTITION_POWERTEC is not set -CONFIG_ACORN_PARTITION_RISCIX=y -CONFIG_OSF_PARTITION=y -CONFIG_AMIGA_PARTITION=y -CONFIG_ATARI_PARTITION=y -CONFIG_MAC_PARTITION=y -CONFIG_MSDOS_PARTITION=y -CONFIG_BSD_DISKLABEL=y -CONFIG_MINIX_SUBPARTITION=y -CONFIG_SOLARIS_X86_PARTITION=y -CONFIG_UNIXWARE_DISKLABEL=y -CONFIG_LDM_PARTITION=y -# CONFIG_LDM_DEBUG is not set -CONFIG_SGI_PARTITION=y -CONFIG_ULTRIX_PARTITION=y -CONFIG_SUN_PARTITION=y -CONFIG_KARMA_PARTITION=y -CONFIG_EFI_PARTITION=y -# CONFIG_SYSV68_PARTITION is not set - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -CONFIG_CFQ_GROUP_IOSCHED=y -# CONFIG_DEFAULT_DEADLINE is not set -CONFIG_DEFAULT_CFQ=y -# CONFIG_DEFAULT_NOOP is not set -CONFIG_DEFAULT_IOSCHED="cfq" -# CONFIG_INLINE_SPIN_TRYLOCK is not set -# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set -# CONFIG_INLINE_SPIN_LOCK is not set -# 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_BH is not set -CONFIG_INLINE_SPIN_UNLOCK_IRQ=y -# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set -# CONFIG_INLINE_READ_TRYLOCK is not set -# CONFIG_INLINE_READ_LOCK is not set -# CONFIG_INLINE_READ_LOCK_BH is not set -# CONFIG_INLINE_READ_LOCK_IRQ is not set -# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set -CONFIG_INLINE_READ_UNLOCK=y -# CONFIG_INLINE_READ_UNLOCK_BH is not set -CONFIG_INLINE_READ_UNLOCK_IRQ=y -# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set -# CONFIG_INLINE_WRITE_TRYLOCK is not set -# CONFIG_INLINE_WRITE_LOCK is not set -# CONFIG_INLINE_WRITE_LOCK_BH is not set -# CONFIG_INLINE_WRITE_LOCK_IRQ is not set -# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set -CONFIG_INLINE_WRITE_UNLOCK=y -# CONFIG_INLINE_WRITE_UNLOCK_BH is not set -CONFIG_INLINE_WRITE_UNLOCK_IRQ=y -# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set -# CONFIG_MUTEX_SPIN_ON_OWNER is not set -CONFIG_FREEZER=y - -# -# System Type -# -CONFIG_MMU=y -# CONFIG_ARCH_INTEGRATOR is not set -# CONFIG_ARCH_REALVIEW is not set -# CONFIG_ARCH_VERSATILE is not set -# CONFIG_ARCH_VEXPRESS is not set -# CONFIG_ARCH_AT91 is not set -# CONFIG_ARCH_BCMRING is not set -# CONFIG_ARCH_HIGHBANK is not set -# CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_CNS3XXX is not set -# CONFIG_ARCH_GEMINI is not set -# CONFIG_ARCH_PRIMA2 is not set -# CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_EP93XX is not set -# CONFIG_ARCH_FOOTBRIDGE is not set -# CONFIG_ARCH_MXC is not set -# CONFIG_ARCH_MXS is not set -# CONFIG_ARCH_NETX is not set -# CONFIG_ARCH_H720X is not set -# CONFIG_ARCH_IOP13XX is not set -# CONFIG_ARCH_IOP32X is not set -# CONFIG_ARCH_IOP33X is not set -# CONFIG_ARCH_IXP23XX is not set -# CONFIG_ARCH_IXP2000 is not set -# CONFIG_ARCH_IXP4XX is not set -# CONFIG_ARCH_DOVE is not set -CONFIG_ARCH_KIRKWOOD=y -# CONFIG_ARCH_LPC32XX is not set -# CONFIG_ARCH_MV78XX0 is not set -# CONFIG_ARCH_ORION5X is not set -# CONFIG_ARCH_MMP is not set -# CONFIG_ARCH_KS8695 is not set -# CONFIG_ARCH_W90X900 is not set -# CONFIG_ARCH_TEGRA is not set -# CONFIG_ARCH_PICOXCELL is not set -# 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_S3C24XX is not set -# CONFIG_ARCH_S3C64XX is not set -# CONFIG_ARCH_S5P64X0 is not set -# CONFIG_ARCH_S5PC100 is not set -# CONFIG_ARCH_S5PV210 is not set -# CONFIG_ARCH_EXYNOS is not set -# CONFIG_ARCH_SHARK is not set -# CONFIG_ARCH_U300 is not set -# CONFIG_ARCH_U8500 is not set -# CONFIG_ARCH_NOMADIK is not set -# CONFIG_ARCH_DAVINCI is not set -# CONFIG_ARCH_OMAP is not set -# CONFIG_PLAT_SPEAR is not set -# CONFIG_ARCH_VT8500 is not set -# CONFIG_ARCH_ZYNQ is not set -# CONFIG_GPIO_PCA953X is not set -# CONFIG_KEYBOARD_GPIO_POLLED is not set - -# -# Marvell Kirkwood Implementations -# -# CONFIG_MACH_DB88F6281_BP is not set -# CONFIG_MACH_RD88F6192_NAS is not set -# CONFIG_MACH_RD88F6281 is not set -# CONFIG_MACH_MV88F6281GTW_GE is not set -# CONFIG_MACH_SHEEVAPLUG is not set -# CONFIG_MACH_ESATA_SHEEVAPLUG is not set -# CONFIG_MACH_GURUPLUG is not set -CONFIG_MACH_DREAMPLUG=y -# CONFIG_ARCH_KIRKWOOD_DT is not set -# CONFIG_MACH_DREAMPLUG_DT is not set -# CONFIG_MACH_TS219 is not set -# CONFIG_MACH_TS41X is not set -# CONFIG_MACH_DOCKSTAR is not set -# CONFIG_MACH_OPENRD_BASE is not set -# CONFIG_MACH_OPENRD_CLIENT is not set -# CONFIG_MACH_OPENRD_ULTIMATE is not set -# CONFIG_MACH_NETSPACE_V2 is not set -# CONFIG_MACH_INETSPACE_V2 is not set -# CONFIG_MACH_NETSPACE_MAX_V2 is not set -# CONFIG_MACH_D2NET_V2 is not set -# CONFIG_MACH_NET2BIG_V2 is not set -# CONFIG_MACH_NET5BIG_V2 is not set -# CONFIG_MACH_T5325 is not set - -# -# System MMU -# -CONFIG_PLAT_ORION=y - -# -# Processor Type -# -CONFIG_CPU_FEROCEON=y -# CONFIG_CPU_FEROCEON_OLD_ID is not set -CONFIG_CPU_32v5=y -CONFIG_CPU_ABRT_EV5T=y -CONFIG_CPU_PABRT_LEGACY=y -CONFIG_CPU_CACHE_VIVT=y -CONFIG_CPU_COPY_FEROCEON=y -CONFIG_CPU_TLB_FEROCEON=y -CONFIG_CPU_CP15=y -CONFIG_CPU_CP15_MMU=y -CONFIG_CPU_USE_DOMAINS=y - -# -# Processor Features -# -# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set -CONFIG_ARM_THUMB=y -# CONFIG_CPU_ICACHE_DISABLE is not set -# CONFIG_CPU_DCACHE_DISABLE is not set -CONFIG_OUTER_CACHE=y -CONFIG_CACHE_FEROCEON_L2=y -# CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH is not set -# CONFIG_CACHE_L2X0 is not set -CONFIG_ARM_L1_CACHE_SHIFT=5 -CONFIG_ARM_NR_BANKS=8 - -# -# Bus support -# -CONFIG_PCI=y -CONFIG_PCI_SYSCALL=y -# CONFIG_ARCH_SUPPORTS_MSI is not set -# CONFIG_PCI_DEBUG is not set -# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set -# CONFIG_PCI_STUB is not set -# CONFIG_PCI_IOV is not set -# CONFIG_PCI_PRI is not set -# CONFIG_PCI_PASID is not set -# CONFIG_PCCARD is not set - -# -# Kernel Features -# -CONFIG_TICK_ONESHOT=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_GENERIC_CLOCKEVENTS_BUILD=y -CONFIG_VMSPLIT_3G=y -# CONFIG_VMSPLIT_2G is not set -# CONFIG_VMSPLIT_1G is not set -CONFIG_PAGE_OFFSET=0xC0000000 -CONFIG_ARCH_NR_GPIO=0 -# CONFIG_PREEMPT_NONE is not set -CONFIG_PREEMPT_VOLUNTARY=y -# CONFIG_PREEMPT is not set -CONFIG_HZ=100 -CONFIG_AEABI=y -CONFIG_OABI_COMPAT=y -# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set -# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set -CONFIG_HAVE_ARCH_PFN_VALID=y -# CONFIG_HIGHMEM is not set -CONFIG_SELECT_MEMORY_MODEL=y -CONFIG_FLATMEM_MANUAL=y -CONFIG_FLATMEM=y -CONFIG_FLAT_NODE_MEM_MAP=y -CONFIG_HAVE_MEMBLOCK=y -CONFIG_PAGEFLAGS_EXTENDED=y -CONFIG_SPLIT_PTLOCK_CPUS=999999 -# CONFIG_COMPACTION is not set -# CONFIG_PHYS_ADDR_T_64BIT is not set -CONFIG_ZONE_DMA_FLAG=0 -CONFIG_VIRT_TO_BUS=y -# CONFIG_KSM is not set -CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 -CONFIG_NEED_PER_CPU_KM=y -# CONFIG_CLEANCACHE is not set -CONFIG_FORCE_MAX_ZONEORDER=11 -CONFIG_ALIGNMENT_TRAP=y -CONFIG_UACCESS_WITH_MEMCPY=y -# CONFIG_SECCOMP is not set -# CONFIG_CC_STACKPROTECTOR is not set -# CONFIG_DEPRECATED_PARAM_STRUCT is not set - -# -# Boot options -# -# CONFIG_USE_OF is not set -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_CMDLINE="" -# CONFIG_XIP_KERNEL is not set -CONFIG_KEXEC=y -CONFIG_ATAGS_PROC=y -# CONFIG_CRASH_DUMP is not set -# CONFIG_AUTO_ZRELADDR is not set - -# -# CPU Power Management -# -CONFIG_CPU_IDLE=y -CONFIG_CPU_IDLE_GOV_LADDER=y -CONFIG_CPU_IDLE_GOV_MENU=y - -# -# Floating point emulation -# - -# -# At least one emulation must be selected -# -CONFIG_FPE_NWFPE=y -# CONFIG_FPE_NWFPE_XP is not set -# CONFIG_FPE_FASTFPE is not set -# CONFIG_VFP is not set - -# -# Userspace binary formats -# -CONFIG_BINFMT_ELF=y -CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y -CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y -CONFIG_HAVE_AOUT=y -CONFIG_BINFMT_AOUT=m -CONFIG_BINFMT_MISC=m - -# -# Power management options -# -CONFIG_PM_RUNTIME=y -CONFIG_PM=y -CONFIG_PM_DEBUG=y -CONFIG_PM_ADVANCED_DEBUG=y -# CONFIG_APM_EMULATION is not set -CONFIG_CPU_PM=y -# CONFIG_ARM_CPU_SUSPEND is not set -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_UNIX=y -# CONFIG_UNIX_DIAG is not set -CONFIG_XFRM=y -CONFIG_XFRM_USER=m -# CONFIG_XFRM_SUB_POLICY is not set -# CONFIG_XFRM_MIGRATE is not set -# CONFIG_XFRM_STATISTICS is not set -CONFIG_XFRM_IPCOMP=m -CONFIG_NET_KEY=m -# CONFIG_NET_KEY_MIGRATE is not set -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -# CONFIG_IP_FIB_TRIE_STATS is not set -CONFIG_IP_MULTIPLE_TABLES=y -# CONFIG_IP_ROUTE_MULTIPATH is not set -# CONFIG_IP_ROUTE_VERBOSE is not set -CONFIG_IP_ROUTE_CLASSID=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -CONFIG_NET_IPIP=m -CONFIG_NET_IPGRE_DEMUX=m -CONFIG_NET_IPGRE=m -# CONFIG_NET_IPGRE_BROADCAST is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -CONFIG_SYN_COOKIES=y -CONFIG_INET_AH=m -CONFIG_INET_ESP=m -CONFIG_INET_IPCOMP=m -CONFIG_INET_XFRM_TUNNEL=m -CONFIG_INET_TUNNEL=m -CONFIG_INET_XFRM_MODE_TRANSPORT=m -CONFIG_INET_XFRM_MODE_TUNNEL=m -CONFIG_INET_XFRM_MODE_BEET=m -CONFIG_INET_LRO=y -CONFIG_INET_DIAG=y -CONFIG_INET_TCP_DIAG=y -# CONFIG_INET_UDP_DIAG is not set -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_CUBIC=y -CONFIG_DEFAULT_TCP_CONG="cubic" -# CONFIG_TCP_MD5SIG is not set -CONFIG_IPV6=m -# CONFIG_IPV6_PRIVACY is not set -# CONFIG_IPV6_ROUTER_PREF is not set -# CONFIG_IPV6_OPTIMISTIC_DAD is not set -CONFIG_INET6_AH=m -CONFIG_INET6_ESP=m -CONFIG_INET6_IPCOMP=m -# CONFIG_IPV6_MIP6 is not set -CONFIG_INET6_XFRM_TUNNEL=m -CONFIG_INET6_TUNNEL=m -CONFIG_INET6_XFRM_MODE_TRANSPORT=m -CONFIG_INET6_XFRM_MODE_TUNNEL=m -CONFIG_INET6_XFRM_MODE_BEET=m -# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set -CONFIG_IPV6_SIT=m -# CONFIG_IPV6_SIT_6RD is not set -CONFIG_IPV6_NDISC_NODETYPE=y -# CONFIG_IPV6_TUNNEL is not set -CONFIG_IPV6_MULTIPLE_TABLES=y -# CONFIG_IPV6_SUBTREES is not set -# CONFIG_IPV6_MROUTE is not set -# CONFIG_NETLABEL is not set -CONFIG_NETWORK_SECMARK=y -# CONFIG_NETWORK_PHY_TIMESTAMPING is not set -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_NETFILTER_ADVANCED=y -CONFIG_BRIDGE_NETFILTER=y - -# -# Core Netfilter Configuration -# -CONFIG_NETFILTER_NETLINK=m -# CONFIG_NETFILTER_NETLINK_ACCT is not set -CONFIG_NETFILTER_NETLINK_QUEUE=m -CONFIG_NETFILTER_NETLINK_LOG=m -CONFIG_NF_CONNTRACK=m -CONFIG_NF_CONNTRACK_MARK=y -# CONFIG_NF_CONNTRACK_SECMARK is not set -# CONFIG_NF_CONNTRACK_ZONES is not set -CONFIG_NF_CONNTRACK_PROCFS=y -# CONFIG_NF_CONNTRACK_EVENTS is not set -# CONFIG_NF_CONNTRACK_TIMEOUT is not set -# CONFIG_NF_CONNTRACK_TIMESTAMP is not set -CONFIG_NF_CT_PROTO_DCCP=m -CONFIG_NF_CT_PROTO_GRE=m -CONFIG_NF_CT_PROTO_SCTP=m -CONFIG_NF_CT_PROTO_UDPLITE=m -CONFIG_NF_CONNTRACK_AMANDA=m -CONFIG_NF_CONNTRACK_FTP=m -CONFIG_NF_CONNTRACK_H323=m -CONFIG_NF_CONNTRACK_IRC=m -CONFIG_NF_CONNTRACK_BROADCAST=m -CONFIG_NF_CONNTRACK_NETBIOS_NS=m -# CONFIG_NF_CONNTRACK_SNMP is not set -CONFIG_NF_CONNTRACK_PPTP=m -CONFIG_NF_CONNTRACK_SANE=m -CONFIG_NF_CONNTRACK_SIP=m -CONFIG_NF_CONNTRACK_TFTP=m -# CONFIG_NF_CT_NETLINK is not set -# CONFIG_NF_CT_NETLINK_TIMEOUT is not set -CONFIG_NETFILTER_TPROXY=m -CONFIG_NETFILTER_XTABLES=m - -# -# Xtables combined modules -# -CONFIG_NETFILTER_XT_MARK=m -CONFIG_NETFILTER_XT_CONNMARK=m - -# -# Xtables targets -# -# CONFIG_NETFILTER_XT_TARGET_AUDIT is not set -CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m -CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m -# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set -CONFIG_NETFILTER_XT_TARGET_CT=m -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=m -CONFIG_NETFILTER_XT_TARGET_MARK=m -CONFIG_NETFILTER_XT_TARGET_NFLOG=m -CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m -CONFIG_NETFILTER_XT_TARGET_NOTRACK=m -CONFIG_NETFILTER_XT_TARGET_RATEEST=m -CONFIG_NETFILTER_XT_TARGET_TEE=m -CONFIG_NETFILTER_XT_TARGET_TPROXY=m -CONFIG_NETFILTER_XT_TARGET_TRACE=m -# CONFIG_NETFILTER_XT_TARGET_SECMARK is not set -CONFIG_NETFILTER_XT_TARGET_TCPMSS=m -CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m - -# -# Xtables matches -# -# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set -CONFIG_NETFILTER_XT_MATCH_CLUSTER=m -CONFIG_NETFILTER_XT_MATCH_COMMENT=m -CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m -CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m -CONFIG_NETFILTER_XT_MATCH_CONNMARK=m -CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m -CONFIG_NETFILTER_XT_MATCH_CPU=m -CONFIG_NETFILTER_XT_MATCH_DCCP=m -# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set -CONFIG_NETFILTER_XT_MATCH_DSCP=m -CONFIG_NETFILTER_XT_MATCH_ECN=m -CONFIG_NETFILTER_XT_MATCH_ESP=m -CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m -CONFIG_NETFILTER_XT_MATCH_HELPER=m -CONFIG_NETFILTER_XT_MATCH_HL=m -CONFIG_NETFILTER_XT_MATCH_IPRANGE=m -CONFIG_NETFILTER_XT_MATCH_LENGTH=m -CONFIG_NETFILTER_XT_MATCH_LIMIT=m -CONFIG_NETFILTER_XT_MATCH_MAC=m -CONFIG_NETFILTER_XT_MATCH_MARK=m -CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m -# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set -CONFIG_NETFILTER_XT_MATCH_OSF=m -CONFIG_NETFILTER_XT_MATCH_OWNER=m -CONFIG_NETFILTER_XT_MATCH_POLICY=m -# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set -CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m -CONFIG_NETFILTER_XT_MATCH_QUOTA=m -CONFIG_NETFILTER_XT_MATCH_RATEEST=m -CONFIG_NETFILTER_XT_MATCH_REALM=m -CONFIG_NETFILTER_XT_MATCH_RECENT=m -CONFIG_NETFILTER_XT_MATCH_SCTP=m -CONFIG_NETFILTER_XT_MATCH_SOCKET=m -CONFIG_NETFILTER_XT_MATCH_STATE=m -CONFIG_NETFILTER_XT_MATCH_STATISTIC=m -CONFIG_NETFILTER_XT_MATCH_STRING=m -CONFIG_NETFILTER_XT_MATCH_TCPMSS=m -CONFIG_NETFILTER_XT_MATCH_TIME=m -CONFIG_NETFILTER_XT_MATCH_U32=m -# CONFIG_IP_SET is not set -# CONFIG_IP_VS is not set - -# -# IP: Netfilter Configuration -# -CONFIG_NF_DEFRAG_IPV4=m -CONFIG_NF_CONNTRACK_IPV4=m -CONFIG_NF_CONNTRACK_PROC_COMPAT=y -# CONFIG_IP_NF_QUEUE is not set -CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_AH=m -CONFIG_IP_NF_MATCH_ECN=m -CONFIG_IP_NF_MATCH_RPFILTER=m -CONFIG_IP_NF_MATCH_TTL=m -CONFIG_IP_NF_FILTER=m -CONFIG_IP_NF_TARGET_REJECT=m -CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_NF_NAT=m -CONFIG_NF_NAT_NEEDED=y -CONFIG_IP_NF_TARGET_MASQUERADE=m -CONFIG_IP_NF_TARGET_NETMAP=m -CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_NF_NAT_PROTO_DCCP=m -CONFIG_NF_NAT_PROTO_GRE=m -CONFIG_NF_NAT_PROTO_UDPLITE=m -CONFIG_NF_NAT_PROTO_SCTP=m -CONFIG_NF_NAT_FTP=m -CONFIG_NF_NAT_IRC=m -CONFIG_NF_NAT_TFTP=m -CONFIG_NF_NAT_AMANDA=m -CONFIG_NF_NAT_PPTP=m -CONFIG_NF_NAT_H323=m -CONFIG_NF_NAT_SIP=m -CONFIG_IP_NF_MANGLE=m -# CONFIG_IP_NF_TARGET_CLUSTERIP is not set -CONFIG_IP_NF_TARGET_ECN=m -CONFIG_IP_NF_TARGET_TTL=m -CONFIG_IP_NF_RAW=m -# CONFIG_IP_NF_SECURITY is not set -CONFIG_IP_NF_ARPTABLES=m -CONFIG_IP_NF_ARPFILTER=m -CONFIG_IP_NF_ARP_MANGLE=m - -# -# IPv6: Netfilter Configuration -# -CONFIG_NF_DEFRAG_IPV6=m -CONFIG_NF_CONNTRACK_IPV6=m -# CONFIG_IP6_NF_QUEUE is not set -CONFIG_IP6_NF_IPTABLES=m -CONFIG_IP6_NF_MATCH_AH=m -CONFIG_IP6_NF_MATCH_EUI64=m -CONFIG_IP6_NF_MATCH_FRAG=m -CONFIG_IP6_NF_MATCH_OPTS=m -CONFIG_IP6_NF_MATCH_HL=m -CONFIG_IP6_NF_MATCH_IPV6HEADER=m -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_FILTER=m -CONFIG_IP6_NF_TARGET_REJECT=m -CONFIG_IP6_NF_MANGLE=m -CONFIG_IP6_NF_RAW=m -# CONFIG_IP6_NF_SECURITY is not set -CONFIG_BRIDGE_NF_EBTABLES=m -CONFIG_BRIDGE_EBT_BROUTE=m -CONFIG_BRIDGE_EBT_T_FILTER=m -CONFIG_BRIDGE_EBT_T_NAT=m -CONFIG_BRIDGE_EBT_802_3=m -CONFIG_BRIDGE_EBT_AMONG=m -CONFIG_BRIDGE_EBT_ARP=m -CONFIG_BRIDGE_EBT_IP=m -CONFIG_BRIDGE_EBT_IP6=m -CONFIG_BRIDGE_EBT_LIMIT=m -CONFIG_BRIDGE_EBT_MARK=m -CONFIG_BRIDGE_EBT_PKTTYPE=m -CONFIG_BRIDGE_EBT_STP=m -CONFIG_BRIDGE_EBT_VLAN=m -CONFIG_BRIDGE_EBT_ARPREPLY=m -CONFIG_BRIDGE_EBT_DNAT=m -CONFIG_BRIDGE_EBT_MARK_T=m -CONFIG_BRIDGE_EBT_REDIRECT=m -CONFIG_BRIDGE_EBT_SNAT=m -CONFIG_BRIDGE_EBT_LOG=m -CONFIG_BRIDGE_EBT_ULOG=m -CONFIG_BRIDGE_EBT_NFLOG=m -# CONFIG_IP_DCCP is not set -CONFIG_IP_SCTP=m -# CONFIG_SCTP_DBG_MSG is not set -# CONFIG_SCTP_DBG_OBJCNT is not set -# CONFIG_SCTP_HMAC_NONE is not set -# CONFIG_SCTP_HMAC_SHA1 is not set -CONFIG_SCTP_HMAC_MD5=y -# CONFIG_RDS is not set -# CONFIG_TIPC is not set -# CONFIG_ATM is not set -CONFIG_L2TP=m -# CONFIG_L2TP_DEBUGFS is not set -# CONFIG_L2TP_V3 is not set -CONFIG_STP=m -CONFIG_BRIDGE=m -CONFIG_BRIDGE_IGMP_SNOOPING=y -CONFIG_NET_DSA=m -# CONFIG_NET_DSA_TAG_DSA is not set -# CONFIG_NET_DSA_TAG_EDSA is not set -# CONFIG_NET_DSA_TAG_TRAILER is not set -CONFIG_VLAN_8021Q=m -# CONFIG_VLAN_8021Q_GVRP is not set -# CONFIG_DECNET is not set -CONFIG_LLC=m -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -CONFIG_ATALK=m -CONFIG_DEV_APPLETALK=m -# CONFIG_IPDDP is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_PHONET is not set -# CONFIG_IEEE802154 is not set -CONFIG_NET_SCHED=y - -# -# Queueing/Scheduling -# -CONFIG_NET_SCH_CBQ=m -CONFIG_NET_SCH_HTB=m -CONFIG_NET_SCH_HFSC=m -CONFIG_NET_SCH_PRIO=m -CONFIG_NET_SCH_MULTIQ=m -CONFIG_NET_SCH_RED=m -# CONFIG_NET_SCH_SFB is not set -CONFIG_NET_SCH_SFQ=m -CONFIG_NET_SCH_TEQL=m -CONFIG_NET_SCH_TBF=m -CONFIG_NET_SCH_GRED=m -CONFIG_NET_SCH_DSMARK=m -CONFIG_NET_SCH_NETEM=m -CONFIG_NET_SCH_DRR=m -# CONFIG_NET_SCH_MQPRIO is not set -# CONFIG_NET_SCH_CHOKE is not set -# CONFIG_NET_SCH_QFQ is not set -# CONFIG_NET_SCH_INGRESS is not set -# CONFIG_NET_SCH_PLUG is not set - -# -# Classification -# -CONFIG_NET_CLS=y -CONFIG_NET_CLS_BASIC=m -CONFIG_NET_CLS_TCINDEX=m -CONFIG_NET_CLS_ROUTE4=m -CONFIG_NET_CLS_FW=m -CONFIG_NET_CLS_U32=m -CONFIG_CLS_U32_PERF=y -CONFIG_CLS_U32_MARK=y -CONFIG_NET_CLS_RSVP=m -CONFIG_NET_CLS_RSVP6=m -CONFIG_NET_CLS_FLOW=m -CONFIG_NET_CLS_CGROUP=y -CONFIG_NET_EMATCH=y -CONFIG_NET_EMATCH_STACK=32 -CONFIG_NET_EMATCH_CMP=m -CONFIG_NET_EMATCH_NBYTE=m -CONFIG_NET_EMATCH_U32=m -CONFIG_NET_EMATCH_META=m -CONFIG_NET_EMATCH_TEXT=m -CONFIG_NET_CLS_ACT=y -# CONFIG_NET_ACT_POLICE is not set -# CONFIG_NET_ACT_GACT is not set -# CONFIG_NET_ACT_MIRRED is not set -# CONFIG_NET_ACT_IPT is not set -# CONFIG_NET_ACT_NAT is not set -# CONFIG_NET_ACT_PEDIT is not set -# CONFIG_NET_ACT_SIMP is not set -# CONFIG_NET_ACT_SKBEDIT is not set -CONFIG_NET_ACT_CSUM=m -# CONFIG_NET_CLS_IND is not set -CONFIG_NET_SCH_FIFO=y -# CONFIG_DCB is not set -CONFIG_DNS_RESOLVER=y -# CONFIG_BATMAN_ADV is not set -# CONFIG_OPENVSWITCH is not set -CONFIG_NETPRIO_CGROUP=m -CONFIG_BQL=y -CONFIG_HAVE_BPF_JIT=y -# CONFIG_BPF_JIT is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -# CONFIG_NET_DROP_MONITOR is not set -# CONFIG_HAMRADIO is not set -# CONFIG_CAN is not set -# CONFIG_IRDA is not set -CONFIG_BT=m -CONFIG_BT_RFCOMM=m -CONFIG_BT_RFCOMM_TTY=y -CONFIG_BT_BNEP=m -CONFIG_BT_BNEP_MC_FILTER=y -CONFIG_BT_BNEP_PROTO_FILTER=y -CONFIG_BT_HIDP=m - -# -# Bluetooth device drivers -# -CONFIG_BT_HCIBTUSB=m -CONFIG_BT_HCIBTSDIO=m -CONFIG_BT_HCIUART=m -# CONFIG_BT_HCIUART_H4 is not set -# CONFIG_BT_HCIUART_BCSP is not set -# CONFIG_BT_HCIUART_ATH3K is not set -# CONFIG_BT_HCIUART_LL is not set -CONFIG_BT_HCIBCM203X=m -CONFIG_BT_HCIBPA10X=m -CONFIG_BT_HCIBFUSB=m -CONFIG_BT_HCIVHCI=m -CONFIG_BT_MRVL=m -CONFIG_BT_MRVL_SDIO=m -CONFIG_BT_ATH3K=m -CONFIG_BT_WILINK=m -CONFIG_AF_RXRPC=m -# CONFIG_AF_RXRPC_DEBUG is not set -CONFIG_RXKAD=m -CONFIG_FIB_RULES=y -CONFIG_WIRELESS=y -CONFIG_WIRELESS_EXT=y -CONFIG_WEXT_CORE=y -CONFIG_WEXT_PROC=y -CONFIG_WEXT_SPY=y -CONFIG_WEXT_PRIV=y -CONFIG_CFG80211=m -# CONFIG_NL80211_TESTMODE is not set -# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set -# CONFIG_CFG80211_REG_DEBUG is not set -CONFIG_CFG80211_DEFAULT_PS=y -# CONFIG_CFG80211_DEBUGFS is not set -# CONFIG_CFG80211_INTERNAL_REGDB is not set -CONFIG_CFG80211_WEXT=y -# CONFIG_WIRELESS_EXT_SYSFS is not set -CONFIG_LIB80211=m -CONFIG_LIB80211_CRYPT_WEP=m -CONFIG_LIB80211_CRYPT_CCMP=m -CONFIG_LIB80211_CRYPT_TKIP=m -# CONFIG_LIB80211_DEBUG is not set -CONFIG_MAC80211=m -CONFIG_MAC80211_HAS_RC=y -# CONFIG_MAC80211_RC_PID is not set -CONFIG_MAC80211_RC_MINSTREL=y -CONFIG_MAC80211_RC_MINSTREL_HT=y -CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y -CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" -CONFIG_MAC80211_MESH=y -CONFIG_MAC80211_LEDS=y -# CONFIG_MAC80211_DEBUGFS is not set -# CONFIG_MAC80211_DEBUG_MENU is not set -CONFIG_WIMAX=m -CONFIG_WIMAX_DEBUG_LEVEL=8 -CONFIG_RFKILL=m -CONFIG_RFKILL_LEDS=y -CONFIG_RFKILL_INPUT=y -# CONFIG_RFKILL_REGULATOR is not set -CONFIG_NET_9P=m -# CONFIG_NET_9P_DEBUG is not set -# CONFIG_CAIF is not set -CONFIG_CEPH_LIB=m -# CONFIG_CEPH_LIB_PRETTYDEBUG is not set -# CONFIG_CEPH_LIB_USE_DNS_RESOLVER is not set -# CONFIG_NFC is not set - -# -# Device Drivers -# - -# -# Generic Driver Options -# -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -# CONFIG_DEVTMPFS is not set -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=y -CONFIG_FIRMWARE_IN_KERNEL=y -CONFIG_EXTRA_FIRMWARE="" -# CONFIG_DEBUG_DRIVER is not set -# CONFIG_DEBUG_DEVRES is not set -# CONFIG_SYS_HYPERVISOR is not set -# CONFIG_GENERIC_CPU_DEVICES is not set -CONFIG_REGMAP=y -CONFIG_REGMAP_I2C=m -CONFIG_REGMAP_SPI=m -# CONFIG_DMA_SHARED_BUFFER is not set -CONFIG_CONNECTOR=m -CONFIG_MTD=y -# CONFIG_MTD_TESTS is not set -# CONFIG_MTD_REDBOOT_PARTS is not set -CONFIG_MTD_CMDLINE_PARTS=y -# CONFIG_MTD_AFS_PARTS is not set -CONFIG_MTD_AR7_PARTS=m - -# -# User Modules And Translation Layers -# -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLKDEVS=y -CONFIG_MTD_BLOCK=y -CONFIG_FTL=m -CONFIG_NFTL=m -# CONFIG_NFTL_RW is not set -# CONFIG_INFTL is not set -# CONFIG_RFD_FTL is not set -# CONFIG_SSFDC is not set -# CONFIG_SM_FTL is not set -# CONFIG_MTD_OOPS is not set -CONFIG_MTD_SWAP=m - -# -# RAM/ROM/Flash chip drivers -# -CONFIG_MTD_CFI=y -CONFIG_MTD_JEDECPROBE=y -CONFIG_MTD_GEN_PROBE=y -CONFIG_MTD_CFI_ADV_OPTIONS=y -CONFIG_MTD_CFI_NOSWAP=y -# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set -# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set -CONFIG_MTD_CFI_GEOMETRY=y -CONFIG_MTD_MAP_BANK_WIDTH_1=y -CONFIG_MTD_MAP_BANK_WIDTH_2=y -CONFIG_MTD_MAP_BANK_WIDTH_4=y -# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set -CONFIG_MTD_CFI_I1=y -CONFIG_MTD_CFI_I2=y -CONFIG_MTD_CFI_I4=y -# CONFIG_MTD_CFI_I8 is not set -# CONFIG_MTD_OTP is not set -CONFIG_MTD_CFI_INTELEXT=y -CONFIG_MTD_CFI_AMDSTD=m -CONFIG_MTD_CFI_STAA=m -CONFIG_MTD_CFI_UTIL=y -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -CONFIG_MTD_PHYSMAP=y -# CONFIG_MTD_PHYSMAP_COMPAT is not set -# CONFIG_MTD_IMPA7 is not set -# CONFIG_MTD_INTEL_VR_NOR is not set -# CONFIG_MTD_PLATRAM is not set - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_PMC551 is not set -CONFIG_MTD_DATAFLASH=m -# CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set -# CONFIG_MTD_DATAFLASH_OTP is not set -CONFIG_MTD_M25P80=y -CONFIG_M25PXX_USE_FAST_READ=y -CONFIG_MTD_SST25L=m -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_PHRAM is not set -# CONFIG_MTD_MTDRAM is not set -# CONFIG_MTD_BLOCK2MTD is not set - -# -# Disk-On-Chip Device Drivers -# -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOC2001PLUS is not set -# CONFIG_MTD_DOCG3 is not set -CONFIG_MTD_NAND_ECC=y -# CONFIG_MTD_NAND_ECC_SMC is not set -CONFIG_MTD_NAND=y -# CONFIG_MTD_NAND_VERIFY_WRITE is not set -# CONFIG_MTD_NAND_ECC_BCH is not set -CONFIG_MTD_SM_COMMON=m -# CONFIG_MTD_NAND_MUSEUM_IDS is not set -# CONFIG_MTD_NAND_DENALI is not set -# CONFIG_MTD_NAND_GPIO is not set -CONFIG_MTD_NAND_IDS=y -CONFIG_MTD_NAND_RICOH=m -# CONFIG_MTD_NAND_DISKONCHIP is not set -# CONFIG_MTD_NAND_DOCG4 is not set -# CONFIG_MTD_NAND_CAFE is not set -CONFIG_MTD_NAND_NANDSIM=m -# CONFIG_MTD_NAND_PLATFORM is not set -# CONFIG_MTD_ALAUDA is not set -CONFIG_MTD_NAND_ORION=y -# CONFIG_MTD_ONENAND is not set - -# -# LPDDR flash memory drivers -# -CONFIG_MTD_LPDDR=m -CONFIG_MTD_QINFO_PROBE=m -CONFIG_MTD_UBI=y -CONFIG_MTD_UBI_WL_THRESHOLD=4096 -CONFIG_MTD_UBI_BEB_RESERVE=1 -# CONFIG_MTD_UBI_GLUEBI is not set -# CONFIG_MTD_UBI_DEBUG is not set -CONFIG_PARPORT=m -# CONFIG_PARPORT_PC is not set -# CONFIG_PARPORT_GSC is not set -CONFIG_PARPORT_AX88796=m -CONFIG_PARPORT_1284=y -CONFIG_PARPORT_NOT_PC=y -CONFIG_BLK_DEV=y -# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -# CONFIG_BLK_DEV_COW_COMMON is not set -CONFIG_BLK_DEV_LOOP=m -CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -CONFIG_BLK_DEV_DRBD=m -# CONFIG_DRBD_FAULT_INJECTION is not set -CONFIG_BLK_DEV_NBD=m -# CONFIG_BLK_DEV_NVME is not set -CONFIG_BLK_DEV_OSD=m -# CONFIG_BLK_DEV_SX8 is not set -# CONFIG_BLK_DEV_UB is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_BLK_DEV_RAM_SIZE=8192 -# CONFIG_BLK_DEV_XIP is not set -# CONFIG_CDROM_PKTCDVD is not set -CONFIG_ATA_OVER_ETH=m -# CONFIG_MG_DISK is not set -CONFIG_BLK_DEV_RBD=m - -# -# Misc devices -# -CONFIG_SENSORS_LIS3LV02D=m -CONFIG_AD525X_DPOT=m -CONFIG_AD525X_DPOT_I2C=m -CONFIG_AD525X_DPOT_SPI=m -# CONFIG_PHANTOM is not set -# CONFIG_INTEL_MID_PTI is not set -CONFIG_SGI_IOC4=m -CONFIG_TIFM_CORE=m -CONFIG_TIFM_7XX1=m -CONFIG_ICS932S401=m -CONFIG_ENCLOSURE_SERVICES=m -# CONFIG_HP_ILO is not set -CONFIG_APDS9802ALS=m -CONFIG_ISL29003=m -CONFIG_ISL29020=m -CONFIG_SENSORS_TSL2550=m -CONFIG_SENSORS_BH1780=m -CONFIG_SENSORS_BH1770=m -CONFIG_SENSORS_APDS990X=m -CONFIG_HMC6352=m -CONFIG_DS1682=m -CONFIG_TI_DAC7512=m -CONFIG_BMP085=m -# CONFIG_PCH_PHUB is not set -# CONFIG_USB_SWITCH_FSA9480 is not set -CONFIG_C2PORT=m - -# -# EEPROM support -# -CONFIG_EEPROM_AT24=m -CONFIG_EEPROM_AT25=m -CONFIG_EEPROM_LEGACY=m -CONFIG_EEPROM_MAX6875=m -CONFIG_EEPROM_93CX6=m -# CONFIG_EEPROM_93XX46 is not set -CONFIG_CB710_CORE=m -# CONFIG_CB710_DEBUG is not set -CONFIG_CB710_DEBUG_ASSUMPTIONS=y -CONFIG_IWMC3200TOP=m -# CONFIG_IWMC3200TOP_DEBUG is not set -# CONFIG_IWMC3200TOP_DEBUGFS is not set - -# -# Texas Instruments shared transport line discipline -# -CONFIG_TI_ST=m -# CONFIG_SENSORS_LIS3_SPI is not set -CONFIG_SENSORS_LIS3_I2C=m - -# -# Altera FPGA firmware download module -# -# CONFIG_ALTERA_STAPL is not set -CONFIG_HAVE_IDE=y -# CONFIG_IDE is not set - -# -# SCSI device support -# -CONFIG_SCSI_MOD=y -CONFIG_RAID_ATTRS=m -CONFIG_SCSI=y -CONFIG_SCSI_DMA=y -CONFIG_SCSI_TGT=m -CONFIG_SCSI_NETLINK=y -# CONFIG_SCSI_PROC_FS is not set - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=m -CONFIG_CHR_DEV_ST=m -CONFIG_CHR_DEV_OSST=m -CONFIG_BLK_DEV_SR=m -CONFIG_BLK_DEV_SR_VENDOR=y -CONFIG_CHR_DEV_SG=m -CONFIG_CHR_DEV_SCH=m -CONFIG_SCSI_ENCLOSURE=m -CONFIG_SCSI_MULTI_LUN=y -CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_LOGGING=y -CONFIG_SCSI_SCAN_ASYNC=y -CONFIG_SCSI_WAIT_SCAN=m - -# -# SCSI Transports -# -CONFIG_SCSI_SPI_ATTRS=m -CONFIG_SCSI_FC_ATTRS=m -CONFIG_SCSI_FC_TGT_ATTRS=y -CONFIG_SCSI_ISCSI_ATTRS=m -CONFIG_SCSI_SAS_ATTRS=m -CONFIG_SCSI_SAS_LIBSAS=m -CONFIG_SCSI_SAS_ATA=y -CONFIG_SCSI_SAS_HOST_SMP=y -CONFIG_SCSI_SRP_ATTRS=m -CONFIG_SCSI_SRP_TGT_ATTRS=y -CONFIG_SCSI_LOWLEVEL=y -CONFIG_ISCSI_TCP=m -CONFIG_ISCSI_BOOT_SYSFS=m -CONFIG_SCSI_CXGB3_ISCSI=m -CONFIG_SCSI_CXGB4_ISCSI=m -CONFIG_SCSI_BNX2_ISCSI=m -CONFIG_SCSI_BNX2X_FCOE=m -CONFIG_BE2ISCSI=m -# CONFIG_BLK_DEV_3W_XXXX_RAID is not set -CONFIG_SCSI_HPSA=m -# CONFIG_SCSI_3W_9XXX is not set -CONFIG_SCSI_3W_SAS=m -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AACRAID is not set -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_AIC79XX is not set -# CONFIG_SCSI_AIC94XX is not set -# CONFIG_SCSI_MVSAS is not set -CONFIG_SCSI_MVUMI=m -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_ARCMSR is not set -# CONFIG_MEGARAID_NEWGEN is not set -# CONFIG_MEGARAID_LEGACY is not set -# CONFIG_MEGARAID_SAS is not set -CONFIG_SCSI_MPT2SAS=m -CONFIG_SCSI_MPT2SAS_MAX_SGE=128 -# CONFIG_SCSI_MPT2SAS_LOGGING is not set -# CONFIG_SCSI_UFSHCD is not set -# CONFIG_SCSI_HPTIOP is not set -CONFIG_LIBFC=m -CONFIG_LIBFCOE=m -CONFIG_FCOE=m -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -# CONFIG_SCSI_IPS is not set -# CONFIG_SCSI_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_STEX is not set -# CONFIG_SCSI_SYM53C8XX_2 is not set -# CONFIG_SCSI_IPR is not set -# CONFIG_SCSI_QLOGIC_1280 is not set -# CONFIG_SCSI_QLA_FC is not set -# CONFIG_SCSI_QLA_ISCSI is not set -# CONFIG_SCSI_LPFC is not set -# CONFIG_SCSI_DC395x is not set -# CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_NSP32 is not set -# CONFIG_SCSI_DEBUG is not set -CONFIG_SCSI_PMCRAID=m -CONFIG_SCSI_PM8001=m -CONFIG_SCSI_SRP=m -CONFIG_SCSI_BFA_FC=m -CONFIG_SCSI_DH=m -CONFIG_SCSI_DH_RDAC=m -CONFIG_SCSI_DH_HP_SW=m -CONFIG_SCSI_DH_EMC=m -CONFIG_SCSI_DH_ALUA=m -CONFIG_SCSI_OSD_INITIATOR=m -CONFIG_SCSI_OSD_ULD=m -CONFIG_SCSI_OSD_DPRINT_SENSE=1 -# CONFIG_SCSI_OSD_DEBUG is not set -CONFIG_ATA=y -# CONFIG_ATA_NONSTANDARD is not set -CONFIG_ATA_VERBOSE_ERROR=y -CONFIG_SATA_PMP=y - -# -# Controllers with non-SFF native interface -# -CONFIG_SATA_AHCI=m -# CONFIG_SATA_AHCI_PLATFORM is not set -# CONFIG_SATA_INIC162X is not set -# CONFIG_SATA_ACARD_AHCI is not set -# CONFIG_SATA_SIL24 is not set -CONFIG_ATA_SFF=y - -# -# SFF controllers with custom DMA interface -# -# CONFIG_PDC_ADMA is not set -# CONFIG_SATA_QSTOR is not set -# CONFIG_SATA_SX4 is not set -CONFIG_ATA_BMDMA=y - -# -# SATA SFF controllers with BMDMA -# -# CONFIG_ATA_PIIX is not set -CONFIG_SATA_MV=y -# CONFIG_SATA_NV is not set -# CONFIG_SATA_PROMISE is not set -# CONFIG_SATA_SIL is not set -# CONFIG_SATA_SIS is not set -# CONFIG_SATA_SVW is not set -# CONFIG_SATA_ULI is not set -# CONFIG_SATA_VIA is not set -# CONFIG_SATA_VITESSE is not set - -# -# PATA SFF controllers with BMDMA -# -# CONFIG_PATA_ALI is not set -# CONFIG_PATA_AMD is not set -# CONFIG_PATA_ARASAN_CF is not set -# CONFIG_PATA_ARTOP is not set -# CONFIG_PATA_ATIIXP is not set -# CONFIG_PATA_ATP867X is not set -# CONFIG_PATA_CMD64X is not set -# CONFIG_PATA_CS5520 is not set -# CONFIG_PATA_CS5530 is not set -# CONFIG_PATA_CS5536 is not set -# CONFIG_PATA_CYPRESS is not set -# CONFIG_PATA_EFAR is not set -# CONFIG_PATA_HPT366 is not set -# CONFIG_PATA_HPT37X is not set -# CONFIG_PATA_HPT3X2N is not set -# CONFIG_PATA_HPT3X3 is not set -# CONFIG_PATA_IT8213 is not set -# CONFIG_PATA_IT821X is not set -# CONFIG_PATA_JMICRON is not set -# CONFIG_PATA_MARVELL is not set -# CONFIG_PATA_NETCELL is not set -# CONFIG_PATA_NINJA32 is not set -# CONFIG_PATA_NS87415 is not set -# CONFIG_PATA_OLDPIIX is not set -# CONFIG_PATA_OPTIDMA is not set -# CONFIG_PATA_PDC2027X is not set -# CONFIG_PATA_PDC_OLD is not set -# CONFIG_PATA_RADISYS is not set -# CONFIG_PATA_RDC is not set -# CONFIG_PATA_SC1200 is not set -# CONFIG_PATA_SCH is not set -# CONFIG_PATA_SERVERWORKS is not set -# CONFIG_PATA_SIL680 is not set -# CONFIG_PATA_SIS is not set -# CONFIG_PATA_TOSHIBA is not set -# CONFIG_PATA_TRIFLEX is not set -# CONFIG_PATA_VIA is not set -# CONFIG_PATA_WINBOND is not set - -# -# PIO-only SFF controllers -# -# CONFIG_PATA_CMD640_PCI is not set -# CONFIG_PATA_MPIIX is not set -# CONFIG_PATA_NS87410 is not set -# CONFIG_PATA_OPTI is not set -# CONFIG_PATA_PLATFORM is not set -# CONFIG_PATA_RZ1000 is not set - -# -# Generic fallback / legacy drivers -# -# CONFIG_ATA_GENERIC is not set -# CONFIG_PATA_LEGACY is not set -CONFIG_MD=y -CONFIG_BLK_DEV_MD=m -CONFIG_MD_LINEAR=m -CONFIG_MD_RAID0=m -CONFIG_MD_RAID1=m -CONFIG_MD_RAID10=m -CONFIG_MD_RAID456=m -CONFIG_MD_MULTIPATH=m -CONFIG_MD_FAULTY=m -CONFIG_BLK_DEV_DM=m -# CONFIG_DM_DEBUG is not set -CONFIG_DM_CRYPT=m -CONFIG_DM_SNAPSHOT=m -# CONFIG_DM_THIN_PROVISIONING is not set -CONFIG_DM_MIRROR=m -CONFIG_DM_RAID=m -CONFIG_DM_LOG_USERSPACE=m -CONFIG_DM_ZERO=m -CONFIG_DM_MULTIPATH=m -CONFIG_DM_MULTIPATH_QL=m -CONFIG_DM_MULTIPATH_ST=m -# CONFIG_DM_DELAY is not set -CONFIG_DM_UEVENT=y -# CONFIG_DM_FLAKEY is not set -# CONFIG_DM_VERITY is not set -CONFIG_TARGET_CORE=m -CONFIG_TCM_IBLOCK=m -CONFIG_TCM_FILEIO=m -CONFIG_TCM_PSCSI=m -CONFIG_LOOPBACK_TARGET=m -CONFIG_TCM_FC=m -# CONFIG_ISCSI_TARGET is not set -CONFIG_FUSION=y -CONFIG_FUSION_SPI=m -CONFIG_FUSION_FC=m -CONFIG_FUSION_SAS=m -CONFIG_FUSION_MAX_SGE=128 -CONFIG_FUSION_CTL=m -# CONFIG_FUSION_LOGGING is not set - -# -# IEEE 1394 (FireWire) support -# -CONFIG_FIREWIRE=m -CONFIG_FIREWIRE_OHCI=m -CONFIG_FIREWIRE_SBP2=m -CONFIG_FIREWIRE_NET=m -CONFIG_FIREWIRE_NOSY=m -# CONFIG_I2O is not set -CONFIG_NETDEVICES=y -CONFIG_NET_CORE=y -CONFIG_BONDING=m -CONFIG_DUMMY=m -CONFIG_EQUALIZER=m -# CONFIG_NET_FC is not set -CONFIG_MII=m -CONFIG_IFB=m -# CONFIG_NET_TEAM is not set -CONFIG_MACVLAN=m -CONFIG_MACVTAP=m -CONFIG_NETCONSOLE=m -CONFIG_NETCONSOLE_DYNAMIC=y -CONFIG_NETPOLL=y -# CONFIG_NETPOLL_TRAP is not set -CONFIG_NET_POLL_CONTROLLER=y -CONFIG_TUN=m -CONFIG_VETH=m -# CONFIG_ARCNET is not set - -# -# CAIF transport drivers -# - -# -# Distributed Switch Architecture drivers -# -# CONFIG_NET_DSA_MV88E6XXX is not set -# CONFIG_NET_DSA_MV88E6060 is not set -# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set -# CONFIG_NET_DSA_MV88E6131 is not set -# CONFIG_NET_DSA_MV88E6123_61_65 is not set -CONFIG_ETHERNET=y -CONFIG_MDIO=m -# CONFIG_NET_VENDOR_3COM is not set -# CONFIG_NET_VENDOR_ADAPTEC is not set -# CONFIG_NET_VENDOR_ALTEON is not set -# CONFIG_NET_VENDOR_AMD is not set -# CONFIG_NET_VENDOR_ATHEROS is not set -CONFIG_NET_VENDOR_BROADCOM=y -# CONFIG_B44 is not set -CONFIG_BNX2=m -CONFIG_CNIC=m -# CONFIG_TIGON3 is not set -# CONFIG_BNX2X is not set -# CONFIG_NET_VENDOR_BROCADE is not set -# CONFIG_NET_CALXEDA_XGMAC is not set -CONFIG_NET_VENDOR_CHELSIO=y -# CONFIG_CHELSIO_T1 is not set -CONFIG_CHELSIO_T3=m -CONFIG_CHELSIO_T4=m -# CONFIG_CHELSIO_T4VF is not set -# CONFIG_NET_VENDOR_CIRRUS is not set -# CONFIG_NET_VENDOR_CISCO is not set -# CONFIG_DM9000 is not set -# CONFIG_DNET is not set -# CONFIG_NET_VENDOR_DEC is not set -# CONFIG_NET_VENDOR_DLINK is not set -# CONFIG_NET_VENDOR_EMULEX is not set -# CONFIG_NET_VENDOR_EXAR is not set -# CONFIG_NET_VENDOR_FARADAY is not set -# CONFIG_NET_VENDOR_HP is not set -# CONFIG_NET_VENDOR_INTEL is not set -# CONFIG_IP1000 is not set -# CONFIG_JME is not set -CONFIG_NET_VENDOR_MARVELL=y -CONFIG_MV643XX_ETH=y -# CONFIG_SKGE is not set -# CONFIG_SKY2 is not set -CONFIG_NET_VENDOR_MELLANOX=y -# CONFIG_MLX4_EN is not set -# CONFIG_MLX4_CORE is not set -# CONFIG_NET_VENDOR_MICREL is not set -# CONFIG_NET_VENDOR_MICROCHIP is not set -# CONFIG_NET_VENDOR_MYRI is not set -# CONFIG_FEALNX is not set -# CONFIG_NET_VENDOR_NATSEMI is not set -# CONFIG_NET_VENDOR_NVIDIA is not set -# CONFIG_NET_VENDOR_OKI is not set -# CONFIG_ETHOC is not set -# CONFIG_NET_PACKET_ENGINE is not set -# CONFIG_NET_VENDOR_QLOGIC is not set -# CONFIG_NET_VENDOR_REALTEK is not set -# CONFIG_NET_VENDOR_RDC is not set -# CONFIG_NET_VENDOR_SEEQ is not set -# CONFIG_NET_VENDOR_SILAN is not set -# CONFIG_NET_VENDOR_SIS is not set -# CONFIG_SFC is not set -# CONFIG_NET_VENDOR_SMSC is not set -# CONFIG_NET_VENDOR_STMICRO is not set -# CONFIG_NET_VENDOR_SUN is not set -# CONFIG_NET_VENDOR_TEHUTI is not set -# CONFIG_NET_VENDOR_TI is not set -# CONFIG_NET_VENDOR_VIA is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -CONFIG_PHYLIB=y - -# -# MII PHY device drivers -# -# CONFIG_AMD_PHY is not set -CONFIG_MARVELL_PHY=m -# CONFIG_DAVICOM_PHY is not set -# CONFIG_QSEMI_PHY is not set -CONFIG_LXT_PHY=m -# CONFIG_CICADA_PHY is not set -# CONFIG_VITESSE_PHY is not set -# CONFIG_SMSC_PHY is not set -CONFIG_BROADCOM_PHY=m -# CONFIG_ICPLUS_PHY is not set -CONFIG_REALTEK_PHY=m -CONFIG_NATIONAL_PHY=m -# CONFIG_STE10XP is not set -# CONFIG_LSI_ET1011C_PHY is not set -# CONFIG_MICREL_PHY is not set -# CONFIG_FIXED_PHY is not set -# CONFIG_MDIO_BITBANG is not set -# CONFIG_MICREL_KS8995MA is not set -# CONFIG_PLIP is not set -CONFIG_PPP=m -CONFIG_PPP_BSDCOMP=m -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_FILTER=y -CONFIG_PPP_MPPE=m -CONFIG_PPP_MULTILINK=y -CONFIG_PPPOE=m -CONFIG_PPTP=m -CONFIG_PPPOL2TP=m -CONFIG_PPP_ASYNC=m -CONFIG_PPP_SYNC_TTY=m -CONFIG_SLIP=m -CONFIG_SLHC=m -CONFIG_SLIP_COMPRESSED=y -CONFIG_SLIP_SMART=y -CONFIG_SLIP_MODE_SLIP6=y -# CONFIG_TR is not set - -# -# USB Network Adapters -# -CONFIG_USB_CATC=m -CONFIG_USB_KAWETH=m -CONFIG_USB_PEGASUS=m -CONFIG_USB_RTL8150=m -CONFIG_USB_USBNET=m -CONFIG_USB_NET_AX8817X=m -CONFIG_USB_NET_CDCETHER=m -CONFIG_USB_NET_CDC_EEM=m -CONFIG_USB_NET_CDC_NCM=m -CONFIG_USB_NET_DM9601=m -CONFIG_USB_NET_SMSC75XX=m -CONFIG_USB_NET_SMSC95XX=m -CONFIG_USB_NET_GL620A=m -CONFIG_USB_NET_NET1080=m -CONFIG_USB_NET_PLUSB=m -CONFIG_USB_NET_MCS7830=m -CONFIG_USB_NET_RNDIS_HOST=m -CONFIG_USB_NET_CDC_SUBSET=m -CONFIG_USB_ALI_M5632=y -CONFIG_USB_AN2720=y -CONFIG_USB_BELKIN=y -CONFIG_USB_ARMLINUX=y -CONFIG_USB_EPSON2888=y -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=m -CONFIG_USB_HSO=m -CONFIG_USB_NET_INT51X1=m -CONFIG_USB_IPHETH=m -CONFIG_USB_SIERRA_NET=m -CONFIG_USB_VL600=m -CONFIG_WLAN=y -CONFIG_LIBERTAS_THINFIRM=m -# CONFIG_LIBERTAS_THINFIRM_DEBUG is not set -CONFIG_LIBERTAS_THINFIRM_USB=m -CONFIG_LIBERTAS_UAP=m -# CONFIG_ATMEL is not set -CONFIG_AT76C50X_USB=m -# CONFIG_PRISM54 is not set -# CONFIG_USB_ZD1201 is not set -CONFIG_USB_NET_RNDIS_WLAN=m -CONFIG_RTL8180=m -CONFIG_RTL8187=m -CONFIG_RTL8187_LEDS=y -CONFIG_ADM8211=m -CONFIG_MAC80211_HWSIM=m -CONFIG_MWL8K=m -CONFIG_ATH_COMMON=m -# CONFIG_ATH_DEBUG is not set -CONFIG_ATH5K=m -# CONFIG_ATH5K_DEBUG is not set -# CONFIG_ATH5K_TRACER is not set -CONFIG_ATH5K_PCI=y -CONFIG_ATH9K_HW=m -CONFIG_ATH9K_COMMON=m -CONFIG_ATH9K_BTCOEX_SUPPORT=y -CONFIG_ATH9K=m -CONFIG_ATH9K_PCI=y -# 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_HTC=m -# CONFIG_ATH9K_HTC_DEBUGFS is not set -CONFIG_CARL9170=m -CONFIG_CARL9170_LEDS=y -CONFIG_CARL9170_WPC=y -# CONFIG_CARL9170_HWRNG is not set -CONFIG_ATH6KL=m -CONFIG_ATH6KL_SDIO=m -CONFIG_ATH6KL_USB=m -# CONFIG_ATH6KL_DEBUG is not set -CONFIG_B43=m -CONFIG_B43_SSB=y -CONFIG_B43_PCI_AUTOSELECT=y -CONFIG_B43_PCICORE_AUTOSELECT=y -CONFIG_B43_SDIO=y -CONFIG_B43_PIO=y -CONFIG_B43_PHY_N=y -CONFIG_B43_PHY_LP=y -# CONFIG_B43_PHY_HT is not set -CONFIG_B43_LEDS=y -CONFIG_B43_HWRNG=y -# CONFIG_B43_DEBUG is not set -CONFIG_B43LEGACY=m -CONFIG_B43LEGACY_PCI_AUTOSELECT=y -CONFIG_B43LEGACY_PCICORE_AUTOSELECT=y -CONFIG_B43LEGACY_LEDS=y -CONFIG_B43LEGACY_HWRNG=y -CONFIG_B43LEGACY_DEBUG=y -CONFIG_B43LEGACY_DMA=y -CONFIG_B43LEGACY_PIO=y -CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y -# CONFIG_B43LEGACY_DMA_MODE is not set -# CONFIG_B43LEGACY_PIO_MODE is not set -CONFIG_BRCMUTIL=m -CONFIG_BRCMFMAC=m -CONFIG_BRCMFMAC_SDIO=y -CONFIG_BRCMFMAC_USB=y -# CONFIG_BRCMDBG is not set -CONFIG_HOSTAP=m -CONFIG_HOSTAP_FIRMWARE=y -# CONFIG_HOSTAP_FIRMWARE_NVRAM is not set -CONFIG_HOSTAP_PLX=m -CONFIG_HOSTAP_PCI=m -CONFIG_IPW2100=m -# CONFIG_IPW2100_MONITOR is not set -# CONFIG_IPW2100_DEBUG is not set -CONFIG_IPW2200=m -CONFIG_IPW2200_MONITOR=y -CONFIG_IPW2200_RADIOTAP=y -CONFIG_IPW2200_PROMISCUOUS=y -CONFIG_IPW2200_QOS=y -# CONFIG_IPW2200_DEBUG is not set -CONFIG_LIBIPW=m -# CONFIG_LIBIPW_DEBUG is not set -CONFIG_IWLWIFI=m - -# -# Debugging Options -# -# CONFIG_IWLWIFI_DEBUG is not set -# CONFIG_IWLWIFI_DEVICE_TRACING is not set -# CONFIG_IWLWIFI_P2P is not set -# CONFIG_IWLWIFI_EXPERIMENTAL_MFP is not set -CONFIG_IWLEGACY=m -CONFIG_IWL4965=m -CONFIG_IWL3945=m - -# -# iwl3945 / iwl4965 Debugging Options -# -# CONFIG_IWLEGACY_DEBUG is not set -CONFIG_IWM=m -# CONFIG_IWM_DEBUG is not set -# CONFIG_IWM_TRACING is not set -CONFIG_LIBERTAS=m -CONFIG_LIBERTAS_USB=m -CONFIG_LIBERTAS_SDIO=m -CONFIG_LIBERTAS_SPI=m -# CONFIG_LIBERTAS_DEBUG is not set -CONFIG_LIBERTAS_MESH=y -CONFIG_HERMES=m -CONFIG_HERMES_PRISM=y -CONFIG_HERMES_CACHE_FW_ON_INIT=y -# CONFIG_PLX_HERMES is not set -# CONFIG_TMD_HERMES is not set -# CONFIG_NORTEL_HERMES is not set -# CONFIG_PCI_HERMES is not set -CONFIG_ORINOCO_USB=m -CONFIG_P54_COMMON=m -CONFIG_P54_USB=m -CONFIG_P54_PCI=m -CONFIG_P54_SPI=m -# CONFIG_P54_SPI_DEFAULT_EEPROM is not set -CONFIG_P54_LEDS=y -CONFIG_RT2X00=m -CONFIG_RT2400PCI=m -CONFIG_RT2500PCI=m -CONFIG_RT61PCI=m -CONFIG_RT2800PCI=m -CONFIG_RT2800PCI_RT33XX=y -CONFIG_RT2800PCI_RT35XX=y -CONFIG_RT2800PCI_RT53XX=y -CONFIG_RT2500USB=m -CONFIG_RT73USB=m -CONFIG_RT2800USB=m -CONFIG_RT2800USB_RT33XX=y -CONFIG_RT2800USB_RT35XX=y -CONFIG_RT2800USB_RT53XX=y -# CONFIG_RT2800USB_UNKNOWN is not set -CONFIG_RT2800_LIB=m -CONFIG_RT2X00_LIB_PCI=m -CONFIG_RT2X00_LIB_USB=m -CONFIG_RT2X00_LIB=m -CONFIG_RT2X00_LIB_FIRMWARE=y -CONFIG_RT2X00_LIB_CRYPTO=y -CONFIG_RT2X00_LIB_LEDS=y -# CONFIG_RT2X00_DEBUG is not set -CONFIG_RTL8192CE=m -CONFIG_RTL8192SE=m -# CONFIG_RTL8192DE is not set -CONFIG_RTL8192CU=m -CONFIG_RTLWIFI=m -# CONFIG_RTLWIFI_DEBUG is not set -CONFIG_RTL8192C_COMMON=m -CONFIG_WL1251=m -CONFIG_WL1251_SPI=m -CONFIG_WL1251_SDIO=m -CONFIG_WL12XX_MENU=m -CONFIG_WL12XX=m -CONFIG_WL12XX_SPI=m -CONFIG_WL12XX_SDIO=m -CONFIG_WL12XX_PLATFORM_DATA=y -CONFIG_ZD1211RW=m -# CONFIG_ZD1211RW_DEBUG is not set -CONFIG_MWIFIEX=m -CONFIG_MWIFIEX_SDIO=m -# CONFIG_MWIFIEX_PCIE is not set - -# -# WiMAX Wireless Broadband devices -# -CONFIG_WIMAX_I2400M=m -CONFIG_WIMAX_I2400M_USB=m -CONFIG_WIMAX_I2400M_SDIO=m -CONFIG_WIMAX_IWMC3200_SDIO=y -CONFIG_WIMAX_I2400M_DEBUG_LEVEL=8 -# CONFIG_WAN is not set -# CONFIG_VMXNET3 is not set -# CONFIG_ISDN is not set - -# -# Input device support -# -CONFIG_INPUT=y -CONFIG_INPUT_FF_MEMLESS=m -CONFIG_INPUT_POLLDEV=m -CONFIG_INPUT_SPARSEKMAP=m - -# -# Userland interfaces -# -CONFIG_INPUT_MOUSEDEV=m -CONFIG_INPUT_MOUSEDEV_PSAUX=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_JOYDEV=m -CONFIG_INPUT_EVDEV=m -# CONFIG_INPUT_EVBUG is not set - -# -# Input Device Drivers -# -CONFIG_INPUT_KEYBOARD=y -# CONFIG_KEYBOARD_ADP5588 is not set -# CONFIG_KEYBOARD_ADP5589 is not set -CONFIG_KEYBOARD_ATKBD=m -# CONFIG_KEYBOARD_QT1070 is not set -# CONFIG_KEYBOARD_QT2160 is not set -# CONFIG_KEYBOARD_LKKBD is not set -CONFIG_KEYBOARD_GPIO=m -# CONFIG_KEYBOARD_TCA6416 is not set -# CONFIG_KEYBOARD_TCA8418 is not set -# CONFIG_KEYBOARD_MATRIX is not set -CONFIG_KEYBOARD_LM8323=m -CONFIG_KEYBOARD_MAX7359=m -# CONFIG_KEYBOARD_MCS is not set -# CONFIG_KEYBOARD_MPR121 is not set -# CONFIG_KEYBOARD_NEWTON is not set -CONFIG_KEYBOARD_OPENCORES=m -CONFIG_KEYBOARD_STOWAWAY=m -# CONFIG_KEYBOARD_SUNKBD is not set -# CONFIG_KEYBOARD_OMAP4 is not set -# CONFIG_KEYBOARD_XTKBD is not set -CONFIG_INPUT_MOUSE=y -CONFIG_MOUSE_PS2=m -CONFIG_MOUSE_PS2_ALPS=y -CONFIG_MOUSE_PS2_LOGIPS2PP=y -CONFIG_MOUSE_PS2_SYNAPTICS=y -CONFIG_MOUSE_PS2_TRACKPOINT=y -CONFIG_MOUSE_PS2_ELANTECH=y -CONFIG_MOUSE_PS2_SENTELIC=y -# CONFIG_MOUSE_PS2_TOUCHKIT is not set -# CONFIG_MOUSE_SERIAL is not set -CONFIG_MOUSE_APPLETOUCH=m -# CONFIG_MOUSE_BCM5974 is not set -# 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=y -# CONFIG_INPUT_AD714X is not set -# CONFIG_INPUT_BMA150 is not set -# CONFIG_INPUT_MMA8450 is not set -# CONFIG_INPUT_MPU3050 is not set -# CONFIG_INPUT_GP2A is not set -# CONFIG_INPUT_GPIO_TILT_POLLED is not set -# CONFIG_INPUT_ATI_REMOTE2 is not set -# CONFIG_INPUT_KEYSPAN_REMOTE is not set -# CONFIG_INPUT_KXTJ9 is not set -# CONFIG_INPUT_POWERMATE is not set -# CONFIG_INPUT_YEALINK is not set -# CONFIG_INPUT_CM109 is not set -CONFIG_INPUT_UINPUT=m -# CONFIG_INPUT_PCF50633_PMU is not set -# CONFIG_INPUT_PCF8574 is not set -# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set -# CONFIG_INPUT_ADXL34X is not set -# CONFIG_INPUT_CMA3000 is not set - -# -# Hardware I/O ports -# -CONFIG_SERIO=y -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_PARKBD is not set -# CONFIG_SERIO_PCIPS2 is not set -CONFIG_SERIO_LIBPS2=y -# CONFIG_SERIO_RAW is not set -# CONFIG_SERIO_ALTERA_PS2 is not set -# CONFIG_SERIO_PS2MULT is not set -# CONFIG_GAMEPORT is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_CONSOLE_TRANSLATIONS=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -CONFIG_VT_HW_CONSOLE_BINDING=y -CONFIG_UNIX98_PTYS=y -CONFIG_DEVPTS_MULTIPLE_INSTANCES=y -# CONFIG_LEGACY_PTYS is not set -# CONFIG_SERIAL_NONSTANDARD is not set -CONFIG_NOZOMI=m -CONFIG_N_GSM=m -# CONFIG_TRACE_SINK is not set -# CONFIG_DEVKMEM is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_SERIAL_8250_PCI=y -CONFIG_SERIAL_8250_NR_UARTS=4 -CONFIG_SERIAL_8250_RUNTIME_UARTS=2 -# CONFIG_SERIAL_8250_EXTENDED is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_MAX3100=m -# CONFIG_SERIAL_MAX3107 is not set -CONFIG_SERIAL_MFD_HSU=m -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -# CONFIG_SERIAL_JSM is not set -# CONFIG_SERIAL_TIMBERDALE is not set -# CONFIG_SERIAL_ALTERA_JTAGUART is not set -# CONFIG_SERIAL_ALTERA_UART is not set -# CONFIG_SERIAL_IFX6X60 is not set -# CONFIG_SERIAL_PCH_UART is not set -# CONFIG_SERIAL_XILINX_PS_UART is not set -# CONFIG_TTY_PRINTK is not set -# CONFIG_PRINTER is not set -# CONFIG_PPDEV is not set -# CONFIG_HVC_DCC is not set -# CONFIG_IPMI_HANDLER is not set -CONFIG_HW_RANDOM=m -CONFIG_HW_RANDOM_TIMERIOMEM=m -# CONFIG_NVRAM is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_TCG_TPM is not set -CONFIG_DEVPORT=y -CONFIG_RAMOOPS=m -CONFIG_I2C=y -CONFIG_I2C_BOARDINFO=y -CONFIG_I2C_COMPAT=y -CONFIG_I2C_CHARDEV=m -# CONFIG_I2C_MUX is not set -CONFIG_I2C_HELPER_AUTO=y -CONFIG_I2C_ALGOBIT=m -CONFIG_I2C_ALGOPCA=m - -# -# I2C Hardware Bus support -# - -# -# PC SMBus host controller drivers -# -# CONFIG_I2C_ALI1535 is not set -# CONFIG_I2C_ALI1563 is not set -# CONFIG_I2C_ALI15X3 is not set -# CONFIG_I2C_AMD756 is not set -# CONFIG_I2C_AMD8111 is not set -# CONFIG_I2C_I801 is not set -CONFIG_I2C_ISCH=m -# CONFIG_I2C_PIIX4 is not set -# CONFIG_I2C_NFORCE2 is not set -# CONFIG_I2C_SIS5595 is not set -# CONFIG_I2C_SIS630 is not set -# CONFIG_I2C_SIS96X is not set -# CONFIG_I2C_VIA is not set -# CONFIG_I2C_VIAPRO is not set - -# -# I2C system bus drivers (mostly embedded / system-on-chip) -# -# CONFIG_I2C_DESIGNWARE_PCI is not set -# CONFIG_I2C_EG20T is not set -# CONFIG_I2C_GPIO is not set -# CONFIG_I2C_INTEL_MID is not set -CONFIG_I2C_MV64XXX=y -CONFIG_I2C_OCORES=m -CONFIG_I2C_PCA_PLATFORM=m -# CONFIG_I2C_PXA_PCI is not set -CONFIG_I2C_SIMTEC=m -# CONFIG_I2C_XILINX is not set - -# -# External I2C/SMBus adapter drivers -# -CONFIG_I2C_DIOLAN_U2C=m -# CONFIG_I2C_PARPORT is not set -# CONFIG_I2C_PARPORT_LIGHT is not set -# CONFIG_I2C_TAOS_EVM is not set -# CONFIG_I2C_TINY_USB is not set - -# -# Other I2C/SMBus bus drivers -# -# CONFIG_I2C_STUB is not set -# CONFIG_I2C_DEBUG_CORE is not set -# CONFIG_I2C_DEBUG_ALGO is not set -# CONFIG_I2C_DEBUG_BUS is not set -CONFIG_SPI=y -# CONFIG_SPI_DEBUG is not set -CONFIG_SPI_MASTER=y - -# -# SPI Master Controller Drivers -# -# CONFIG_SPI_ALTERA is not set -CONFIG_SPI_BITBANG=m -CONFIG_SPI_BUTTERFLY=m -# CONFIG_SPI_GPIO is not set -CONFIG_SPI_LM70_LLP=m -# CONFIG_SPI_OC_TINY is not set -CONFIG_SPI_ORION=y -# CONFIG_SPI_PXA2XX_PCI is not set -# CONFIG_SPI_TOPCLIFF_PCH is not set -# CONFIG_SPI_XILINX is not set -# CONFIG_SPI_DESIGNWARE is not set - -# -# SPI Protocol Masters -# -# CONFIG_SPI_SPIDEV is not set -CONFIG_SPI_TLE62X0=m -# CONFIG_HSI is not set - -# -# PPS support -# -CONFIG_PPS=m -# CONFIG_PPS_DEBUG is not set - -# -# PPS clients support -# -# CONFIG_PPS_CLIENT_KTIMER is not set -CONFIG_PPS_CLIENT_LDISC=m -CONFIG_PPS_CLIENT_PARPORT=m -# CONFIG_PPS_CLIENT_GPIO is not set - -# -# PPS generators support -# - -# -# PTP clock support -# -CONFIG_PTP_1588_CLOCK=m - -# -# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks. -# -CONFIG_ARCH_REQUIRE_GPIOLIB=y -CONFIG_GPIOLIB=y -# CONFIG_DEBUG_GPIO is not set -CONFIG_GPIO_SYSFS=y - -# -# Memory mapped GPIO drivers: -# -# CONFIG_GPIO_GENERIC_PLATFORM is not set -# CONFIG_GPIO_VX855 is not set - -# -# I2C GPIO expanders: -# -# CONFIG_GPIO_MAX7300 is not set -# CONFIG_GPIO_MAX732X is not set -# CONFIG_GPIO_PCF857X is not set -# CONFIG_GPIO_SX150X is not set -# CONFIG_GPIO_ADP5588 is not set - -# -# PCI GPIO expanders: -# -# CONFIG_GPIO_BT8XX is not set -# CONFIG_GPIO_ML_IOH is not set -# CONFIG_GPIO_RDC321X is not set - -# -# SPI GPIO expanders: -# -# CONFIG_GPIO_MAX7301 is not set -# CONFIG_GPIO_MCP23S08 is not set -# CONFIG_GPIO_MC33880 is not set -# CONFIG_GPIO_74X164 is not set - -# -# AC97 GPIO expanders: -# - -# -# MODULbus GPIO expanders: -# -CONFIG_W1=m -CONFIG_W1_CON=y - -# -# 1-wire Bus Masters -# -CONFIG_W1_MASTER_MATROX=m -CONFIG_W1_MASTER_DS2490=m -CONFIG_W1_MASTER_DS2482=m -# CONFIG_W1_MASTER_DS1WM is not set -# CONFIG_W1_MASTER_GPIO is not set - -# -# 1-wire Slaves -# -CONFIG_W1_SLAVE_THERM=m -CONFIG_W1_SLAVE_SMEM=m -# CONFIG_W1_SLAVE_DS2408 is not set -# CONFIG_W1_SLAVE_DS2423 is not set -CONFIG_W1_SLAVE_DS2431=m -CONFIG_W1_SLAVE_DS2433=m -# CONFIG_W1_SLAVE_DS2433_CRC is not set -CONFIG_W1_SLAVE_DS2760=m -# CONFIG_W1_SLAVE_DS2780 is not set -# CONFIG_W1_SLAVE_DS2781 is not set -CONFIG_W1_SLAVE_BQ27000=m -CONFIG_POWER_SUPPLY=m -# CONFIG_POWER_SUPPLY_DEBUG is not set -# CONFIG_PDA_POWER is not set -# CONFIG_TEST_POWER is not set -# CONFIG_BATTERY_DS2760 is not set -# CONFIG_BATTERY_DS2780 is not set -# CONFIG_BATTERY_DS2781 is not set -CONFIG_BATTERY_DS2782=m -# CONFIG_BATTERY_SBS is not set -CONFIG_BATTERY_BQ27x00=m -CONFIG_BATTERY_BQ27X00_I2C=y -CONFIG_BATTERY_BQ27X00_PLATFORM=y -CONFIG_BATTERY_MAX17040=m -# CONFIG_BATTERY_MAX17042 is not set -CONFIG_CHARGER_PCF50633=m -# CONFIG_CHARGER_ISP1704 is not set -# CONFIG_CHARGER_MAX8903 is not set -# 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=m -CONFIG_HWMON_VID=m -# CONFIG_HWMON_DEBUG_CHIP is not set - -# -# Native drivers -# -# CONFIG_SENSORS_AD7314 is not set -CONFIG_SENSORS_AD7414=m -CONFIG_SENSORS_AD7418=m -CONFIG_SENSORS_ADCXX=m -# CONFIG_SENSORS_ADM1021 is not set -# CONFIG_SENSORS_ADM1025 is not set -# CONFIG_SENSORS_ADM1026 is not set -CONFIG_SENSORS_ADM1029=m -# CONFIG_SENSORS_ADM1031 is not set -CONFIG_SENSORS_ADM9240=m -CONFIG_SENSORS_ADT7411=m -CONFIG_SENSORS_ADT7462=m -CONFIG_SENSORS_ADT7470=m -CONFIG_SENSORS_ADT7475=m -CONFIG_SENSORS_ASC7621=m -CONFIG_SENSORS_ATXP1=m -CONFIG_SENSORS_DS620=m -# CONFIG_SENSORS_DS1621 is not set -CONFIG_SENSORS_I5K_AMB=m -# CONFIG_SENSORS_F71805F is not set -CONFIG_SENSORS_F71882FG=m -CONFIG_SENSORS_F75375S=m -CONFIG_SENSORS_G760A=m -# CONFIG_SENSORS_GL518SM is not set -# CONFIG_SENSORS_GL520SM is not set -# CONFIG_SENSORS_GPIO_FAN is not set -# CONFIG_SENSORS_IT87 is not set -# CONFIG_SENSORS_JC42 is not set -CONFIG_SENSORS_LINEAGE=m -# CONFIG_SENSORS_LM63 is not set -CONFIG_SENSORS_LM70=m -CONFIG_SENSORS_LM73=m -# CONFIG_SENSORS_LM75 is not set -# CONFIG_SENSORS_LM77 is not set -# CONFIG_SENSORS_LM78 is not set -# CONFIG_SENSORS_LM80 is not set -# CONFIG_SENSORS_LM83 is not set -# CONFIG_SENSORS_LM85 is not set -# CONFIG_SENSORS_LM87 is not set -# CONFIG_SENSORS_LM90 is not set -# CONFIG_SENSORS_LM92 is not set -CONFIG_SENSORS_LM93=m -CONFIG_SENSORS_LTC4151=m -CONFIG_SENSORS_LTC4215=m -CONFIG_SENSORS_LTC4245=m -CONFIG_SENSORS_LTC4261=m -CONFIG_SENSORS_LM95241=m -# CONFIG_SENSORS_LM95245 is not set -CONFIG_SENSORS_MAX1111=m -CONFIG_SENSORS_MAX16065=m -# CONFIG_SENSORS_MAX1619 is not set -# CONFIG_SENSORS_MAX1668 is not set -CONFIG_SENSORS_MAX6639=m -CONFIG_SENSORS_MAX6642=m -CONFIG_SENSORS_MAX6650=m -# CONFIG_SENSORS_MCP3021 is not set -# CONFIG_SENSORS_NTC_THERMISTOR is not set -# CONFIG_SENSORS_PC87360 is not set -CONFIG_SENSORS_PC87427=m -# CONFIG_SENSORS_PCF8591 is not set -# CONFIG_PMBUS is not set -# CONFIG_SENSORS_SHT15 is not set -CONFIG_SENSORS_SHT21=m -# CONFIG_SENSORS_SIS5595 is not set -# CONFIG_SENSORS_SMM665 is not set -CONFIG_SENSORS_DME1737=m -CONFIG_SENSORS_EMC1403=m -# CONFIG_SENSORS_EMC2103 is not set -CONFIG_SENSORS_EMC6W201=m -# CONFIG_SENSORS_SMSC47M1 is not set -CONFIG_SENSORS_SMSC47M192=m -# CONFIG_SENSORS_SMSC47B397 is not set -CONFIG_SENSORS_SCH56XX_COMMON=m -CONFIG_SENSORS_SCH5627=m -# CONFIG_SENSORS_SCH5636 is not set -CONFIG_SENSORS_ADS1015=m -CONFIG_SENSORS_ADS7828=m -CONFIG_SENSORS_ADS7871=m -CONFIG_SENSORS_AMC6821=m -CONFIG_SENSORS_THMC50=m -CONFIG_SENSORS_TMP102=m -CONFIG_SENSORS_TMP401=m -CONFIG_SENSORS_TMP421=m -# CONFIG_SENSORS_VIA686A is not set -CONFIG_SENSORS_VT1211=m -CONFIG_SENSORS_VT8231=m -# CONFIG_SENSORS_W83781D is not set -CONFIG_SENSORS_W83791D=m -CONFIG_SENSORS_W83792D=m -CONFIG_SENSORS_W83793=m -CONFIG_SENSORS_W83795=m -# CONFIG_SENSORS_W83795_FANCTRL is not set -# CONFIG_SENSORS_W83L785TS is not set -CONFIG_SENSORS_W83L786NG=m -# CONFIG_SENSORS_W83627HF is not set -CONFIG_SENSORS_W83627EHF=m -# CONFIG_THERMAL is not set -CONFIG_WATCHDOG=y -CONFIG_WATCHDOG_CORE=y -# CONFIG_WATCHDOG_NOWAYOUT is not set - -# -# Watchdog Device Drivers -# -CONFIG_SOFT_WATCHDOG=m -CONFIG_ORION_WATCHDOG=m -# CONFIG_MAX63XX_WATCHDOG is not set -# CONFIG_ALIM7101_WDT is not set - -# -# PCI-based Watchdog Cards -# -# CONFIG_PCIPCWATCHDOG is not set -# CONFIG_WDTPCI is not set - -# -# USB-based Watchdog Cards -# -# CONFIG_USBPCWATCHDOG is not set -CONFIG_SSB_POSSIBLE=y - -# -# Sonics Silicon Backplane -# -CONFIG_SSB=m -CONFIG_SSB_SPROM=y -CONFIG_SSB_BLOCKIO=y -CONFIG_SSB_PCIHOST_POSSIBLE=y -CONFIG_SSB_PCIHOST=y -CONFIG_SSB_B43_PCI_BRIDGE=y -CONFIG_SSB_SDIOHOST_POSSIBLE=y -CONFIG_SSB_SDIOHOST=y -# CONFIG_SSB_SILENT is not set -# CONFIG_SSB_DEBUG is not set -CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y -CONFIG_SSB_DRIVER_PCICORE=y -CONFIG_BCMA_POSSIBLE=y - -# -# Broadcom specific AMBA -# -# CONFIG_BCMA is not set - -# -# Multifunction device drivers -# -CONFIG_MFD_CORE=m -# CONFIG_MFD_88PM860X is not set -CONFIG_MFD_SM501=m -# CONFIG_MFD_SM501_GPIO is not set -# CONFIG_MFD_ASIC3 is not set -# CONFIG_HTC_EGPIO is not set -CONFIG_HTC_PASIC3=m -# CONFIG_HTC_I2CPLD is not set -# CONFIG_UCB1400_CORE is not set -# CONFIG_TPS6105X is not set -CONFIG_TPS65010=m -# 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 -# CONFIG_PMIC_DA903X is not set -# CONFIG_MFD_DA9052_SPI is not set -# CONFIG_MFD_DA9052_I2C is not set -# CONFIG_PMIC_ADP5520 is not set -# CONFIG_MFD_MAX8925 is not set -# CONFIG_MFD_MAX8997 is not set -# CONFIG_MFD_MAX8998 is not set -# CONFIG_MFD_S5M_CORE is not set -CONFIG_MFD_WM8400=m -# CONFIG_MFD_WM831X_I2C is not set -# CONFIG_MFD_WM831X_SPI is not set -# CONFIG_MFD_WM8350_I2C is not set -# CONFIG_MFD_WM8994 is not set -CONFIG_MFD_PCF50633=m -CONFIG_PCF50633_ADC=m -CONFIG_PCF50633_GPIO=m -# CONFIG_MFD_MC13XXX is not set -# CONFIG_ABX500_CORE is not set -# CONFIG_EZX_PCAP is not set -# CONFIG_MFD_TIMBERDALE is not set -CONFIG_LPC_SCH=m -# CONFIG_MFD_RDC321X is not set -# CONFIG_MFD_JANZ_CMODIO is not set -# CONFIG_MFD_VX855 is not set -CONFIG_MFD_WL1273_CORE=m -# 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 -CONFIG_REGULATOR_FIXED_VOLTAGE=m -# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set -CONFIG_REGULATOR_USERSPACE_CONSUMER=m -# CONFIG_REGULATOR_GPIO is not set -# CONFIG_REGULATOR_AD5398 is not set -# CONFIG_REGULATOR_ISL6271A is not set -CONFIG_REGULATOR_MAX1586=m -CONFIG_REGULATOR_MAX8649=m -CONFIG_REGULATOR_MAX8660=m -# CONFIG_REGULATOR_MAX8952 is not set -CONFIG_REGULATOR_LP3971=m -# CONFIG_REGULATOR_LP3972 is not set -CONFIG_REGULATOR_PCF50633=m -# CONFIG_REGULATOR_TPS62360 is not set -CONFIG_REGULATOR_TPS65023=m -CONFIG_REGULATOR_TPS6507X=m -# CONFIG_REGULATOR_TPS6524X is not set -CONFIG_REGULATOR_WM8400=m -CONFIG_MEDIA_SUPPORT=m - -# -# Multimedia core support -# -CONFIG_MEDIA_CONTROLLER=y -CONFIG_VIDEO_DEV=m -CONFIG_VIDEO_V4L2_COMMON=m -# CONFIG_VIDEO_V4L2_SUBDEV_API is not set -CONFIG_DVB_CORE=m -CONFIG_DVB_NET=y -CONFIG_VIDEO_MEDIA=m - -# -# Multimedia drivers -# -CONFIG_VIDEO_SAA7146=m -CONFIG_VIDEO_SAA7146_VV=m -CONFIG_RC_CORE=m -CONFIG_LIRC=m -CONFIG_RC_MAP=m -CONFIG_IR_NEC_DECODER=m -CONFIG_IR_RC5_DECODER=m -CONFIG_IR_RC6_DECODER=m -CONFIG_IR_JVC_DECODER=m -CONFIG_IR_SONY_DECODER=m -CONFIG_IR_RC5_SZ_DECODER=m -CONFIG_IR_SANYO_DECODER=m -CONFIG_IR_MCE_KBD_DECODER=m -CONFIG_IR_LIRC_CODEC=m -# CONFIG_RC_ATI_REMOTE is not set -CONFIG_IR_IMON=m -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=y -CONFIG_MEDIA_TUNER=m -# CONFIG_MEDIA_TUNER_CUSTOMISE is not set -CONFIG_MEDIA_TUNER_SIMPLE=m -CONFIG_MEDIA_TUNER_TDA8290=m -CONFIG_MEDIA_TUNER_TDA827X=m -CONFIG_MEDIA_TUNER_TDA18271=m -CONFIG_MEDIA_TUNER_TDA9887=m -CONFIG_MEDIA_TUNER_TEA5761=m -CONFIG_MEDIA_TUNER_TEA5767=m -CONFIG_MEDIA_TUNER_MT20XX=m -CONFIG_MEDIA_TUNER_MT2060=m -CONFIG_MEDIA_TUNER_MT2266=m -CONFIG_MEDIA_TUNER_MT2131=m -CONFIG_MEDIA_TUNER_QT1010=m -CONFIG_MEDIA_TUNER_XC2028=m -CONFIG_MEDIA_TUNER_XC5000=m -CONFIG_MEDIA_TUNER_XC4000=m -CONFIG_MEDIA_TUNER_MXL5005S=m -CONFIG_MEDIA_TUNER_MXL5007T=m -CONFIG_MEDIA_TUNER_MC44S803=m -CONFIG_MEDIA_TUNER_MAX2165=m -CONFIG_MEDIA_TUNER_TDA18218=m -CONFIG_MEDIA_TUNER_TDA18212=m -CONFIG_VIDEO_V4L2=m -CONFIG_VIDEOBUF_GEN=m -CONFIG_VIDEOBUF_DMA_SG=m -CONFIG_VIDEOBUF_VMALLOC=m -CONFIG_VIDEOBUF_DVB=m -CONFIG_VIDEO_TVEEPROM=m -CONFIG_VIDEO_TUNER=m -CONFIG_VIDEOBUF2_CORE=m -CONFIG_VIDEOBUF2_MEMOPS=m -CONFIG_VIDEOBUF2_VMALLOC=m -CONFIG_VIDEO_CAPTURE_DRIVERS=y -# CONFIG_VIDEO_ADV_DEBUG is not set -# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set -CONFIG_VIDEO_HELPER_CHIPS_AUTO=y -CONFIG_VIDEO_IR_I2C=m - -# -# Audio decoders, processors and mixers -# -CONFIG_VIDEO_MSP3400=m -CONFIG_VIDEO_CS53L32A=m -CONFIG_VIDEO_WM8775=m - -# -# RDS decoders -# - -# -# Video decoders -# -CONFIG_VIDEO_SAA711X=m -CONFIG_VIDEO_TVP5150=m - -# -# Video and audio decoders -# -CONFIG_VIDEO_CX25840=m - -# -# MPEG video encoders -# -CONFIG_VIDEO_CX2341X=m - -# -# Video encoders -# - -# -# Camera sensor devices -# -CONFIG_VIDEO_MT9V011=m - -# -# Flash devices -# - -# -# Video improvement chips -# - -# -# Miscelaneous helper chips -# -CONFIG_VIDEO_VIVI=m -CONFIG_V4L_USB_DRIVERS=y -CONFIG_USB_VIDEO_CLASS=m -CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y -CONFIG_USB_GSPCA=m -CONFIG_USB_M5602=m -CONFIG_USB_STV06XX=m -CONFIG_USB_GL860=m -CONFIG_USB_GSPCA_BENQ=m -CONFIG_USB_GSPCA_CONEX=m -CONFIG_USB_GSPCA_CPIA1=m -CONFIG_USB_GSPCA_ETOMS=m -CONFIG_USB_GSPCA_FINEPIX=m -CONFIG_USB_GSPCA_JEILINJ=m -# CONFIG_USB_GSPCA_JL2005BCD is not set -CONFIG_USB_GSPCA_KINECT=m -CONFIG_USB_GSPCA_KONICA=m -CONFIG_USB_GSPCA_MARS=m -CONFIG_USB_GSPCA_MR97310A=m -CONFIG_USB_GSPCA_NW80X=m -CONFIG_USB_GSPCA_OV519=m -CONFIG_USB_GSPCA_OV534=m -CONFIG_USB_GSPCA_OV534_9=m -CONFIG_USB_GSPCA_PAC207=m -CONFIG_USB_GSPCA_PAC7302=m -CONFIG_USB_GSPCA_PAC7311=m -# CONFIG_USB_GSPCA_SE401 is not set -CONFIG_USB_GSPCA_SN9C2028=m -CONFIG_USB_GSPCA_SN9C20X=m -CONFIG_USB_GSPCA_SONIXB=m -CONFIG_USB_GSPCA_SONIXJ=m -CONFIG_USB_GSPCA_SPCA500=m -CONFIG_USB_GSPCA_SPCA501=m -CONFIG_USB_GSPCA_SPCA505=m -CONFIG_USB_GSPCA_SPCA506=m -CONFIG_USB_GSPCA_SPCA508=m -CONFIG_USB_GSPCA_SPCA561=m -CONFIG_USB_GSPCA_SPCA1528=m -CONFIG_USB_GSPCA_SQ905=m -CONFIG_USB_GSPCA_SQ905C=m -CONFIG_USB_GSPCA_SQ930X=m -CONFIG_USB_GSPCA_STK014=m -CONFIG_USB_GSPCA_STV0680=m -CONFIG_USB_GSPCA_SUNPLUS=m -CONFIG_USB_GSPCA_T613=m -# CONFIG_USB_GSPCA_TOPRO is not set -CONFIG_USB_GSPCA_TV8532=m -CONFIG_USB_GSPCA_VC032X=m -CONFIG_USB_GSPCA_VICAM=m -CONFIG_USB_GSPCA_XIRLINK_CIT=m -CONFIG_USB_GSPCA_ZC3XX=m -CONFIG_VIDEO_PVRUSB2=m -CONFIG_VIDEO_PVRUSB2_SYSFS=y -CONFIG_VIDEO_PVRUSB2_DVB=y -# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set -CONFIG_VIDEO_HDPVR=m -CONFIG_VIDEO_EM28XX=m -CONFIG_VIDEO_EM28XX_ALSA=m -CONFIG_VIDEO_EM28XX_DVB=m -# CONFIG_VIDEO_EM28XX_RC is not set -CONFIG_VIDEO_TLG2300=m -CONFIG_VIDEO_CX231XX=m -CONFIG_VIDEO_CX231XX_RC=y -CONFIG_VIDEO_CX231XX_ALSA=m -CONFIG_VIDEO_CX231XX_DVB=m -# CONFIG_VIDEO_TM6000 is not set -CONFIG_VIDEO_USBVISION=m -CONFIG_USB_ET61X251=m -CONFIG_USB_SN9C102=m -CONFIG_USB_PWC=m -# CONFIG_USB_PWC_DEBUG is not set -CONFIG_USB_PWC_INPUT_EVDEV=y -CONFIG_VIDEO_CPIA2=m -CONFIG_USB_ZR364XX=m -CONFIG_USB_STKWEBCAM=m -CONFIG_USB_S2255=m -# CONFIG_V4L_PCI_DRIVERS is not set -# CONFIG_V4L_ISA_PARPORT_DRIVERS is not set -# CONFIG_V4L_PLATFORM_DRIVERS is not set -CONFIG_V4L_MEM2MEM_DRIVERS=y -# CONFIG_VIDEO_MEM2MEM_TESTDEV is not set -CONFIG_RADIO_ADAPTERS=y -CONFIG_RADIO_SI470X=y -CONFIG_USB_SI470X=m -CONFIG_I2C_SI470X=m -CONFIG_USB_MR800=m -# CONFIG_USB_DSBR is not set -# CONFIG_RADIO_MAXIRADIO is not set -CONFIG_I2C_SI4713=m -CONFIG_RADIO_SI4713=m -# CONFIG_USB_KEENE is not set -CONFIG_RADIO_TEA5764=m -CONFIG_RADIO_SAA7706H=m -CONFIG_RADIO_TEF6862=m -CONFIG_RADIO_WL1273=m - -# -# Texas Instruments WL128x FM driver (ST based) -# -CONFIG_RADIO_WL128X=m -CONFIG_DVB_MAX_ADAPTERS=8 -CONFIG_DVB_DYNAMIC_MINORS=y -CONFIG_DVB_CAPTURE_DRIVERS=y - -# -# Supported SAA7146 based PCI Adapters -# -CONFIG_TTPCI_EEPROM=m -CONFIG_DVB_AV7110=m -CONFIG_DVB_AV7110_OSD=y -CONFIG_DVB_BUDGET_CORE=m -CONFIG_DVB_BUDGET=m -CONFIG_DVB_BUDGET_CI=m -CONFIG_DVB_BUDGET_AV=m -CONFIG_DVB_BUDGET_PATCH=m - -# -# Supported USB Adapters -# -CONFIG_DVB_USB=m -# CONFIG_DVB_USB_DEBUG is not set -CONFIG_DVB_USB_A800=m -CONFIG_DVB_USB_DIBUSB_MB=m -CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y -CONFIG_DVB_USB_DIBUSB_MC=m -CONFIG_DVB_USB_DIB0700=m -CONFIG_DVB_USB_UMT_010=m -CONFIG_DVB_USB_CXUSB=m -CONFIG_DVB_USB_M920X=m -CONFIG_DVB_USB_GL861=m -CONFIG_DVB_USB_AU6610=m -CONFIG_DVB_USB_DIGITV=m -CONFIG_DVB_USB_VP7045=m -CONFIG_DVB_USB_VP702X=m -CONFIG_DVB_USB_GP8PSK=m -CONFIG_DVB_USB_NOVA_T_USB2=m -CONFIG_DVB_USB_TTUSB2=m -CONFIG_DVB_USB_DTT200U=m -CONFIG_DVB_USB_OPERA1=m -CONFIG_DVB_USB_AF9005=m -CONFIG_DVB_USB_AF9005_REMOTE=m -# CONFIG_DVB_USB_PCTV452E is not set -CONFIG_DVB_USB_DW2102=m -CONFIG_DVB_USB_CINERGY_T2=m -CONFIG_DVB_USB_ANYSEE=m -CONFIG_DVB_USB_DTV5100=m -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 is not set -# CONFIG_DVB_USB_MXL111SF is not set -# CONFIG_DVB_USB_RTL28XXU is not set -CONFIG_DVB_TTUSB_BUDGET=m -CONFIG_DVB_TTUSB_DEC=m -CONFIG_SMS_SIANO_MDTV=m - -# -# Siano module components -# -CONFIG_SMS_USB_DRV=m -CONFIG_SMS_SDIO_DRV=m - -# -# Supported FlexCopII (B2C2) Adapters -# -CONFIG_DVB_B2C2_FLEXCOP=m -CONFIG_DVB_B2C2_FLEXCOP_PCI=m -CONFIG_DVB_B2C2_FLEXCOP_USB=m -# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set - -# -# Supported BT878 Adapters -# - -# -# Supported Pluto2 Adapters -# -CONFIG_DVB_PLUTO2=m - -# -# Supported SDMC DM1105 Adapters -# -CONFIG_DVB_DM1105=m - -# -# Supported FireWire (IEEE 1394) Adapters -# -CONFIG_DVB_FIREDTV=m -CONFIG_DVB_FIREDTV_INPUT=y - -# -# Supported Earthsoft PT1 Adapters -# -CONFIG_DVB_PT1=m - -# -# Supported Mantis Adapters -# -CONFIG_MANTIS_CORE=m -CONFIG_DVB_MANTIS=m -CONFIG_DVB_HOPPER=m - -# -# Supported nGene Adapters -# -CONFIG_DVB_NGENE=m - -# -# Supported ddbridge ('Octopus') Adapters -# -# CONFIG_DVB_DDBRIDGE is not set - -# -# Supported DVB Frontends -# -# CONFIG_DVB_FE_CUSTOMISE is not set - -# -# Multistandard (satellite) frontends -# -CONFIG_DVB_STB0899=m -CONFIG_DVB_STB6100=m -CONFIG_DVB_STV090x=m -CONFIG_DVB_STV6110x=m - -# -# Multistandard (cable + terrestrial) frontends -# -CONFIG_DVB_DRXK=m -CONFIG_DVB_TDA18271C2DD=m - -# -# DVB-S (satellite) frontends -# -CONFIG_DVB_CX24123=m -CONFIG_DVB_MT312=m -CONFIG_DVB_ZL10039=m -CONFIG_DVB_S5H1420=m -CONFIG_DVB_STV0288=m -CONFIG_DVB_STB6000=m -CONFIG_DVB_STV0299=m -CONFIG_DVB_STV6110=m -CONFIG_DVB_STV0900=m -CONFIG_DVB_TDA8083=m -CONFIG_DVB_TDA10086=m -CONFIG_DVB_TDA8261=m -CONFIG_DVB_VES1X93=m -CONFIG_DVB_TUNER_ITD1000=m -CONFIG_DVB_TUNER_CX24113=m -CONFIG_DVB_TDA826X=m -CONFIG_DVB_TUA6100=m -CONFIG_DVB_CX24116=m -CONFIG_DVB_SI21XX=m -CONFIG_DVB_DS3000=m -CONFIG_DVB_MB86A16=m -CONFIG_DVB_TDA10071=m - -# -# DVB-T (terrestrial) frontends -# -CONFIG_DVB_SP8870=m -CONFIG_DVB_CX22700=m -CONFIG_DVB_CX22702=m -CONFIG_DVB_DRXD=m -CONFIG_DVB_L64781=m -CONFIG_DVB_TDA1004X=m -CONFIG_DVB_NXT6000=m -CONFIG_DVB_MT352=m -CONFIG_DVB_ZL10353=m -CONFIG_DVB_DIB3000MB=m -CONFIG_DVB_DIB3000MC=m -CONFIG_DVB_DIB7000M=m -CONFIG_DVB_DIB7000P=m -CONFIG_DVB_TDA10048=m -CONFIG_DVB_AF9013=m -CONFIG_DVB_EC100=m -CONFIG_DVB_CXD2820R=m - -# -# DVB-C (cable) frontends -# -CONFIG_DVB_VES1820=m -CONFIG_DVB_TDA10021=m -CONFIG_DVB_TDA10023=m -CONFIG_DVB_STV0297=m - -# -# ATSC (North American/Korean Terrestrial/Cable DTV) frontends -# -CONFIG_DVB_NXT200X=m -CONFIG_DVB_BCM3510=m -CONFIG_DVB_LGDT330X=m -CONFIG_DVB_LGDT3305=m -CONFIG_DVB_S5H1409=m -CONFIG_DVB_S5H1411=m - -# -# ISDB-T (terrestrial) frontends -# -CONFIG_DVB_S921=m -CONFIG_DVB_DIB8000=m -CONFIG_DVB_MB86A20S=m - -# -# Digital terrestrial only tuners/PLL -# -CONFIG_DVB_PLL=m -CONFIG_DVB_TUNER_DIB0070=m -CONFIG_DVB_TUNER_DIB0090=m - -# -# SEC control devices for DVB-S -# -CONFIG_DVB_LNBP21=m -CONFIG_DVB_ISL6421=m -CONFIG_DVB_ISL6423=m -CONFIG_DVB_A8293=m -CONFIG_DVB_LGS8GXX=m -CONFIG_DVB_ATBM8830=m -CONFIG_DVB_TDA665x=m -CONFIG_DVB_IX2505V=m -CONFIG_DVB_M88RS2000=m - -# -# Tools to develop new frontends -# -# CONFIG_DVB_DUMMY_FE is not set - -# -# Graphics support -# -# CONFIG_VGA_ARB is not set -# CONFIG_DRM is not set -# CONFIG_STUB_POULSBO is not set -CONFIG_VGASTATE=m -# CONFIG_VIDEO_OUTPUT_CONTROL is not set -CONFIG_FB=m -CONFIG_FIRMWARE_EDID=y -CONFIG_FB_DDC=m -# CONFIG_FB_BOOT_VESA_SUPPORT is not set -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 -CONFIG_FB_SYS_IMAGEBLIT=m -# CONFIG_FB_FOREIGN_ENDIAN is not set -CONFIG_FB_SYS_FOPS=m -# CONFIG_FB_WMT_GE_ROPS is not set -CONFIG_FB_DEFERRED_IO=y -CONFIG_FB_SVGALIB=m -# CONFIG_FB_MACMODES is not set -# CONFIG_FB_BACKLIGHT is not set -CONFIG_FB_MODE_HELPERS=y -CONFIG_FB_TILEBLITTING=y - -# -# Frame buffer hardware drivers -# -# CONFIG_FB_CIRRUS is not set -# CONFIG_FB_PM2 is not set -# CONFIG_FB_CYBER2000 is not set -# CONFIG_FB_UVESA is not set -# CONFIG_FB_S1D13XXX is not set -# CONFIG_FB_NVIDIA is not set -# CONFIG_FB_RIVA is not set -# CONFIG_FB_I740 is not set -# CONFIG_FB_MATROX is not set -# CONFIG_FB_RADEON is not set -# CONFIG_FB_ATY128 is not set -# CONFIG_FB_ATY is not set -CONFIG_FB_S3=m -CONFIG_FB_S3_DDC=y -# CONFIG_FB_SAVAGE is not set -# CONFIG_FB_SIS is not set -# CONFIG_FB_NEOMAGIC is not set -# CONFIG_FB_KYRO is not set -CONFIG_FB_3DFX=m -# CONFIG_FB_3DFX_ACCEL is not set -CONFIG_FB_3DFX_I2C=y -# CONFIG_FB_VOODOO1 is not set -CONFIG_FB_VT8623=m -# CONFIG_FB_TRIDENT is not set -CONFIG_FB_ARK=m -CONFIG_FB_PM3=m -# CONFIG_FB_CARMINE is not set -# CONFIG_FB_TMIO is not set -CONFIG_FB_SM501=m -# CONFIG_FB_SMSCUFX is not set -CONFIG_FB_UDL=m -# CONFIG_FB_VIRTUAL is not set -CONFIG_FB_METRONOME=m -CONFIG_FB_MB862XX=m -CONFIG_FB_MB862XX_PCI_GDC=y -CONFIG_FB_MB862XX_I2C=y -# CONFIG_FB_BROADSHEET is not set -# CONFIG_EXYNOS_VIDEO is not set -CONFIG_BACKLIGHT_LCD_SUPPORT=y -# CONFIG_LCD_CLASS_DEVICE is not set -CONFIG_BACKLIGHT_CLASS_DEVICE=y -# CONFIG_BACKLIGHT_GENERIC is not set -# CONFIG_BACKLIGHT_ADP8860 is not set -# CONFIG_BACKLIGHT_ADP8870 is not set -# CONFIG_BACKLIGHT_PCF50633 is not set -# CONFIG_BACKLIGHT_LP855X is not set - -# -# Console display driver support -# -CONFIG_DUMMY_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE=m -# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set -CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y -# CONFIG_FONTS is not set -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y -# CONFIG_LOGO is not set -CONFIG_SOUND=m -CONFIG_SOUND_OSS_CORE=y -# CONFIG_SOUND_OSS_CORE_PRECLAIM is not set -CONFIG_SND=m -CONFIG_SND_TIMER=m -CONFIG_SND_PCM=m -CONFIG_SND_HWDEP=m -CONFIG_SND_RAWMIDI=m -CONFIG_SND_JACK=y -CONFIG_SND_SEQUENCER=m -CONFIG_SND_SEQ_DUMMY=m -CONFIG_SND_OSSEMUL=y -CONFIG_SND_MIXER_OSS=m -CONFIG_SND_PCM_OSS=m -CONFIG_SND_PCM_OSS_PLUGINS=y -# CONFIG_SND_SEQUENCER_OSS is not set -CONFIG_SND_HRTIMER=m -CONFIG_SND_SEQ_HRTIMER_DEFAULT=y -CONFIG_SND_DYNAMIC_MINORS=y -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=m -# CONFIG_SND_OPL4_LIB_SEQ is not set -# CONFIG_SND_SBAWE_SEQ is not set -# CONFIG_SND_EMU10K1_SEQ is not set -CONFIG_SND_MPU401_UART=m -CONFIG_SND_OPL3_LIB=m -CONFIG_SND_AC97_CODEC=m -CONFIG_SND_DRIVERS=y -# CONFIG_SND_DUMMY is not set -CONFIG_SND_ALOOP=m -# CONFIG_SND_VIRMIDI is not set -# CONFIG_SND_MTPAV is not set -CONFIG_SND_MTS64=m -# CONFIG_SND_SERIAL_U16550 is not set -# CONFIG_SND_MPU401 is not set -CONFIG_SND_PORTMAN2X4=m -CONFIG_SND_AC97_POWER_SAVE=y -CONFIG_SND_AC97_POWER_SAVE_DEFAULT=0 -CONFIG_SND_PCI=y -CONFIG_SND_AD1889=m -CONFIG_SND_ALS300=m -# CONFIG_SND_ALI5451 is not set -# CONFIG_SND_ATIIXP is not set -# CONFIG_SND_ATIIXP_MODEM is not set -# CONFIG_SND_AU8810 is not set -# CONFIG_SND_AU8820 is not set -# CONFIG_SND_AU8830 is not set -# CONFIG_SND_AW2 is not set -# CONFIG_SND_AZT3328 is not set -# CONFIG_SND_BT87X is not set -# CONFIG_SND_CA0106 is not set -# CONFIG_SND_CMIPCI is not set -CONFIG_SND_OXYGEN_LIB=m -CONFIG_SND_OXYGEN=m -# CONFIG_SND_CS4281 is not set -# CONFIG_SND_CS46XX is not set -CONFIG_SND_CS5535AUDIO=m -CONFIG_SND_CTXFI=m -CONFIG_SND_DARLA20=m -CONFIG_SND_GINA20=m -CONFIG_SND_LAYLA20=m -CONFIG_SND_DARLA24=m -CONFIG_SND_GINA24=m -CONFIG_SND_LAYLA24=m -CONFIG_SND_MONA=m -CONFIG_SND_MIA=m -CONFIG_SND_ECHO3G=m -CONFIG_SND_INDIGO=m -CONFIG_SND_INDIGOIO=m -CONFIG_SND_INDIGODJ=m -CONFIG_SND_INDIGOIOX=m -CONFIG_SND_INDIGODJX=m -# CONFIG_SND_EMU10K1 is not set -# CONFIG_SND_EMU10K1X is not set -# CONFIG_SND_ENS1370 is not set -# CONFIG_SND_ENS1371 is not set -# CONFIG_SND_ES1938 is not set -# CONFIG_SND_ES1968 is not set -# CONFIG_SND_FM801 is not set -# CONFIG_SND_HDA_INTEL is not set -# CONFIG_SND_HDSP is not set -CONFIG_SND_HDSPM=m -# CONFIG_SND_ICE1712 is not set -# CONFIG_SND_ICE1724 is not set -# CONFIG_SND_INTEL8X0 is not set -# CONFIG_SND_INTEL8X0M is not set -# CONFIG_SND_KORG1212 is not set -CONFIG_SND_LOLA=m -CONFIG_SND_LX6464ES=m -# CONFIG_SND_MAESTRO3 is not set -# CONFIG_SND_MIXART is not set -# CONFIG_SND_NM256 is not set -CONFIG_SND_PCXHR=m -CONFIG_SND_RIPTIDE=m -# CONFIG_SND_RME32 is not set -# CONFIG_SND_RME96 is not set -# CONFIG_SND_RME9652 is not set -# CONFIG_SND_SONICVIBES is not set -# CONFIG_SND_TRIDENT is not set -# CONFIG_SND_VIA82XX is not set -# CONFIG_SND_VIA82XX_MODEM is not set -CONFIG_SND_VIRTUOSO=m -# CONFIG_SND_VX222 is not set -# CONFIG_SND_YMFPCI is not set -CONFIG_SND_ARM=y -CONFIG_SND_SPI=y -CONFIG_SND_USB=y -CONFIG_SND_USB_AUDIO=m -CONFIG_SND_USB_UA101=m -CONFIG_SND_USB_CAIAQ=m -CONFIG_SND_USB_CAIAQ_INPUT=y -CONFIG_SND_USB_6FIRE=m -CONFIG_SND_FIREWIRE=y -CONFIG_SND_FIREWIRE_LIB=m -CONFIG_SND_FIREWIRE_SPEAKERS=m -CONFIG_SND_ISIGHT=m -CONFIG_SND_SOC=m -CONFIG_SND_KIRKWOOD_SOC=m -CONFIG_SND_SOC_I2C_AND_SPI=m -# CONFIG_SND_SOC_ALL_CODECS is not set -# CONFIG_SOUND_PRIME is not set -CONFIG_AC97_BUS=m -CONFIG_HID_SUPPORT=y -CONFIG_HID=m -# CONFIG_HID_BATTERY_STRENGTH is not set -CONFIG_HIDRAW=y - -# -# USB Input Devices -# -CONFIG_USB_HID=m -CONFIG_HID_PID=y -CONFIG_USB_HIDDEV=y - -# -# USB HID Boot Protocol drivers -# -# CONFIG_USB_KBD is not set -# CONFIG_USB_MOUSE is not set - -# -# Special HID drivers -# -CONFIG_HID_A4TECH=m -CONFIG_HID_ACRUX=m -# CONFIG_HID_ACRUX_FF is not set -# CONFIG_HID_APPLE is not set -CONFIG_HID_BELKIN=m -CONFIG_HID_CHERRY=m -CONFIG_HID_CHICONY=m -CONFIG_HID_PRODIKEYS=m -CONFIG_HID_CYPRESS=m -CONFIG_HID_DRAGONRISE=m -CONFIG_DRAGONRISE_FF=y -CONFIG_HID_EMS_FF=m -CONFIG_HID_ELECOM=m -CONFIG_HID_EZKEY=m -# CONFIG_HID_HOLTEK is not set -CONFIG_HID_KEYTOUCH=m -CONFIG_HID_KYE=m -CONFIG_HID_UCLOGIC=m -CONFIG_HID_WALTOP=m -CONFIG_HID_GYRATION=m -CONFIG_HID_TWINHAN=m -CONFIG_HID_KENSINGTON=m -CONFIG_HID_LCPOWER=m -CONFIG_HID_LOGITECH=m -CONFIG_HID_LOGITECH_DJ=m -CONFIG_LOGITECH_FF=y -CONFIG_LOGIRUMBLEPAD2_FF=y -CONFIG_LOGIG940_FF=y -CONFIG_LOGIWHEELS_FF=y -CONFIG_HID_MAGICMOUSE=m -CONFIG_HID_MICROSOFT=m -CONFIG_HID_MONTEREY=m -CONFIG_HID_MULTITOUCH=m -CONFIG_HID_NTRIG=m -CONFIG_HID_ORTEK=m -CONFIG_HID_PANTHERLORD=m -CONFIG_PANTHERLORD_FF=y -CONFIG_HID_PETALYNX=m -CONFIG_HID_PICOLCD=m -CONFIG_HID_PICOLCD_FB=y -CONFIG_HID_PICOLCD_BACKLIGHT=y -CONFIG_HID_PICOLCD_LEDS=y -# CONFIG_HID_PRIMAX is not set -CONFIG_HID_ROCCAT=m -# CONFIG_HID_SAITEK is not set -CONFIG_HID_SAMSUNG=m -CONFIG_HID_SONY=m -# CONFIG_HID_SPEEDLINK is not set -CONFIG_HID_SUNPLUS=m -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 -CONFIG_HID_WACOM=m -CONFIG_HID_WACOM_POWER_SUPPLY=y -# CONFIG_HID_WIIMOTE is not set -CONFIG_HID_ZEROPLUS=m -CONFIG_ZEROPLUS_FF=y -CONFIG_HID_ZYDACRON=m -CONFIG_USB_ARCH_HAS_OHCI=y -CONFIG_USB_ARCH_HAS_EHCI=y -CONFIG_USB_ARCH_HAS_XHCI=y -CONFIG_USB_SUPPORT=y -CONFIG_USB_COMMON=m -CONFIG_USB_ARCH_HAS_HCD=y -CONFIG_USB=m -# CONFIG_USB_DEBUG is not set -CONFIG_USB_ANNOUNCE_NEW_DEVICES=y - -# -# Miscellaneous USB options -# -CONFIG_USB_DEVICEFS=y -# CONFIG_USB_DEVICE_CLASS is not set -CONFIG_USB_DYNAMIC_MINORS=y -CONFIG_USB_SUSPEND=y -# CONFIG_USB_OTG is not set -# CONFIG_USB_OTG_WHITELIST is not set -# CONFIG_USB_OTG_BLACKLIST_HUB is not set -CONFIG_USB_MON=m -CONFIG_USB_WUSB=m -CONFIG_USB_WUSB_CBAF=m -# CONFIG_USB_WUSB_CBAF_DEBUG is not set - -# -# USB Host Controller Drivers -# -CONFIG_USB_C67X00_HCD=m -CONFIG_USB_XHCI_HCD=m -# CONFIG_USB_XHCI_HCD_DEBUGGING is not set -CONFIG_USB_EHCI_HCD=m -CONFIG_USB_EHCI_ROOT_HUB_TT=y -CONFIG_USB_EHCI_TT_NEWSCHED=y -# 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=m -# CONFIG_USB_OHCI_HCD_SSB is not set -# 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_UHCI_HCD=m -CONFIG_USB_U132_HCD=m -CONFIG_USB_SL811_HCD=m -# CONFIG_USB_SL811_HCD_ISO is not set -CONFIG_USB_R8A66597_HCD=m -CONFIG_USB_WHCI_HCD=m -CONFIG_USB_HWA_HCD=m - -# -# USB Device Class drivers -# -CONFIG_USB_ACM=m -CONFIG_USB_PRINTER=m -CONFIG_USB_WDM=m -CONFIG_USB_TMC=m - -# -# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may -# - -# -# also be needed; see USB_STORAGE Help for more info -# -CONFIG_USB_STORAGE=m -# CONFIG_USB_STORAGE_DEBUG is not set -CONFIG_USB_STORAGE_REALTEK=m -CONFIG_REALTEK_AUTOPM=y -CONFIG_USB_STORAGE_DATAFAB=m -CONFIG_USB_STORAGE_FREECOM=m -CONFIG_USB_STORAGE_ISD200=m -CONFIG_USB_STORAGE_USBAT=m -CONFIG_USB_STORAGE_SDDR09=m -CONFIG_USB_STORAGE_SDDR55=m -CONFIG_USB_STORAGE_JUMPSHOT=m -CONFIG_USB_STORAGE_ALAUDA=m -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 is not set - -# -# USB Imaging devices -# -CONFIG_USB_MDC800=m -CONFIG_USB_MICROTEK=m - -# -# USB port drivers -# -# CONFIG_USB_USS720 is not set -CONFIG_USB_SERIAL=m -CONFIG_USB_EZUSB=y -CONFIG_USB_SERIAL_GENERIC=y -CONFIG_USB_SERIAL_AIRCABLE=m -CONFIG_USB_SERIAL_ARK3116=m -CONFIG_USB_SERIAL_BELKIN=m -CONFIG_USB_SERIAL_CH341=m -CONFIG_USB_SERIAL_WHITEHEAT=m -CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m -CONFIG_USB_SERIAL_CP210X=m -CONFIG_USB_SERIAL_CYPRESS_M8=m -CONFIG_USB_SERIAL_EMPEG=m -CONFIG_USB_SERIAL_FTDI_SIO=m -CONFIG_USB_SERIAL_FUNSOFT=m -CONFIG_USB_SERIAL_VISOR=m -CONFIG_USB_SERIAL_IPAQ=m -CONFIG_USB_SERIAL_IR=m -CONFIG_USB_SERIAL_EDGEPORT=m -CONFIG_USB_SERIAL_EDGEPORT_TI=m -# CONFIG_USB_SERIAL_F81232 is not set -CONFIG_USB_SERIAL_GARMIN=m -CONFIG_USB_SERIAL_IPW=m -CONFIG_USB_SERIAL_IUU=m -CONFIG_USB_SERIAL_KEYSPAN_PDA=m -CONFIG_USB_SERIAL_KEYSPAN=m -# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set -CONFIG_USB_SERIAL_KLSI=m -CONFIG_USB_SERIAL_KOBIL_SCT=m -CONFIG_USB_SERIAL_MCT_U232=m -# CONFIG_USB_SERIAL_METRO is not set -CONFIG_USB_SERIAL_MOS7720=m -CONFIG_USB_SERIAL_MOS7715_PARPORT=y -CONFIG_USB_SERIAL_MOS7840=m -CONFIG_USB_SERIAL_MOTOROLA=m -CONFIG_USB_SERIAL_NAVMAN=m -CONFIG_USB_SERIAL_PL2303=m -CONFIG_USB_SERIAL_OTI6858=m -CONFIG_USB_SERIAL_QCAUX=m -CONFIG_USB_SERIAL_QUALCOMM=m -CONFIG_USB_SERIAL_SPCP8X5=m -CONFIG_USB_SERIAL_HP4X=m -CONFIG_USB_SERIAL_SAFE=m -# CONFIG_USB_SERIAL_SAFE_PADDED is not set -CONFIG_USB_SERIAL_SIEMENS_MPI=m -CONFIG_USB_SERIAL_SIERRAWIRELESS=m -CONFIG_USB_SERIAL_SYMBOL=m -CONFIG_USB_SERIAL_TI=m -CONFIG_USB_SERIAL_CYBERJACK=m -CONFIG_USB_SERIAL_XIRCOM=m -CONFIG_USB_SERIAL_WWAN=m -CONFIG_USB_SERIAL_OPTION=m -CONFIG_USB_SERIAL_OMNINET=m -CONFIG_USB_SERIAL_OPTICON=m -CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m -CONFIG_USB_SERIAL_ZIO=m -CONFIG_USB_SERIAL_SSU100=m -CONFIG_USB_SERIAL_DEBUG=m - -# -# USB Miscellaneous drivers -# -CONFIG_USB_EMI62=m -CONFIG_USB_EMI26=m -CONFIG_USB_ADUTUX=m -CONFIG_USB_SEVSEG=m -CONFIG_USB_RIO500=m -CONFIG_USB_LEGOTOWER=m -CONFIG_USB_LCD=m -CONFIG_USB_LED=m -CONFIG_USB_CYPRESS_CY7C63=m -CONFIG_USB_CYTHERM=m -CONFIG_USB_IDMOUSE=m -CONFIG_USB_FTDI_ELAN=m -CONFIG_USB_APPLEDISPLAY=m -CONFIG_USB_SISUSBVGA=m -CONFIG_USB_SISUSBVGA_CON=y -CONFIG_USB_LD=m -CONFIG_USB_TRANCEVIBRATOR=m -CONFIG_USB_IOWARRIOR=m -CONFIG_USB_TEST=m -CONFIG_USB_ISIGHTFW=m -CONFIG_USB_YUREX=m -# CONFIG_USB_GADGET is not set - -# -# OTG and related infrastructure -# -CONFIG_USB_OTG_UTILS=y -# CONFIG_USB_GPIO_VBUS is not set -# CONFIG_USB_ULPI is not set -CONFIG_NOP_USB_XCEIV=m -CONFIG_UWB=m -CONFIG_UWB_HWA=m -CONFIG_UWB_WHCI=m -CONFIG_UWB_I1480U=m -CONFIG_MMC=m -# CONFIG_MMC_DEBUG is not set -# CONFIG_MMC_UNSAFE_RESUME is not set -# CONFIG_MMC_CLKGATE is not set - -# -# MMC/SD/SDIO Card Drivers -# -CONFIG_MMC_BLOCK=m -CONFIG_MMC_BLOCK_MINORS=8 -CONFIG_MMC_BLOCK_BOUNCE=y -CONFIG_SDIO_UART=m -# CONFIG_MMC_TEST is not set - -# -# MMC/SD/SDIO Host Controller Drivers -# -CONFIG_MMC_SDHCI=m -CONFIG_MMC_SDHCI_PCI=m -CONFIG_MMC_RICOH_MMC=y -CONFIG_MMC_SDHCI_PLTFM=m -CONFIG_MMC_TIFM_SD=m -CONFIG_MMC_MVSDIO=m -CONFIG_MMC_SPI=m -CONFIG_MMC_CB710=m -CONFIG_MMC_VIA_SDMMC=m -# CONFIG_MMC_DW is not set -CONFIG_MMC_VUB300=m -CONFIG_MMC_USHC=m -CONFIG_MEMSTICK=m -# CONFIG_MEMSTICK_DEBUG is not set - -# -# MemoryStick drivers -# -# CONFIG_MEMSTICK_UNSAFE_RESUME is not set -CONFIG_MSPRO_BLOCK=m - -# -# MemoryStick Host Controller Drivers -# -CONFIG_MEMSTICK_TIFM_MS=m -CONFIG_MEMSTICK_JMICRON_38X=m -CONFIG_MEMSTICK_R592=m -CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=y - -# -# LED drivers -# -# CONFIG_LEDS_LM3530 is not set -CONFIG_LEDS_PCA9532=m -# CONFIG_LEDS_PCA9532_GPIO is not set -CONFIG_LEDS_GPIO=y -CONFIG_LEDS_LP3944=m -# CONFIG_LEDS_LP5521 is not set -# CONFIG_LEDS_LP5523 is not set -CONFIG_LEDS_PCA955X=m -# CONFIG_LEDS_PCA9633 is not set -CONFIG_LEDS_DAC124S085=m -CONFIG_LEDS_REGULATOR=m -CONFIG_LEDS_BD2802=m -CONFIG_LEDS_LT3593=m -# CONFIG_LEDS_TCA6507 is not set -# CONFIG_LEDS_OT200 is not set -CONFIG_LEDS_TRIGGERS=y - -# -# LED Triggers -# -CONFIG_LEDS_TRIGGER_TIMER=y -CONFIG_LEDS_TRIGGER_HEARTBEAT=y -CONFIG_LEDS_TRIGGER_BACKLIGHT=y -CONFIG_LEDS_TRIGGER_GPIO=y -CONFIG_LEDS_TRIGGER_DEFAULT_ON=y - -# -# iptables trigger is under Netfilter config (LED target) -# -CONFIG_ACCESSIBILITY=y -CONFIG_A11Y_BRAILLE_CONSOLE=y -# CONFIG_INFINIBAND is not set -CONFIG_RTC_LIB=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_HCTOSYS=y -CONFIG_RTC_HCTOSYS_DEVICE="rtc0" -# CONFIG_RTC_DEBUG is not set - -# -# RTC interfaces -# -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_DRV_TEST is not set - -# -# I2C RTC drivers -# -CONFIG_RTC_DRV_DS1307=m -CONFIG_RTC_DRV_DS1374=m -CONFIG_RTC_DRV_DS1672=m -# CONFIG_RTC_DRV_DS3232 is not set -CONFIG_RTC_DRV_MAX6900=m -CONFIG_RTC_DRV_RS5C372=m -CONFIG_RTC_DRV_ISL1208=m -# CONFIG_RTC_DRV_ISL12022 is not set -CONFIG_RTC_DRV_X1205=m -CONFIG_RTC_DRV_PCF8563=m -CONFIG_RTC_DRV_PCF8583=m -CONFIG_RTC_DRV_M41T80=m -# CONFIG_RTC_DRV_M41T80_WDT is not set -CONFIG_RTC_DRV_BQ32K=m -CONFIG_RTC_DRV_S35390A=y -CONFIG_RTC_DRV_FM3130=m -CONFIG_RTC_DRV_RX8581=m -CONFIG_RTC_DRV_RX8025=m -# CONFIG_RTC_DRV_EM3027 is not set -# CONFIG_RTC_DRV_RV3029C2 is not set - -# -# SPI RTC drivers -# -# CONFIG_RTC_DRV_M41T93 is not set -CONFIG_RTC_DRV_M41T94=m -CONFIG_RTC_DRV_DS1305=m -CONFIG_RTC_DRV_DS1390=m -CONFIG_RTC_DRV_MAX6902=m -CONFIG_RTC_DRV_R9701=m -CONFIG_RTC_DRV_RS5C348=m -CONFIG_RTC_DRV_DS3234=m -CONFIG_RTC_DRV_PCF2123=m - -# -# Platform RTC drivers -# -CONFIG_RTC_DRV_CMOS=m -CONFIG_RTC_DRV_DS1286=m -CONFIG_RTC_DRV_DS1511=m -CONFIG_RTC_DRV_DS1553=m -CONFIG_RTC_DRV_DS1742=m -CONFIG_RTC_DRV_STK17TA8=m -CONFIG_RTC_DRV_M48T86=m -CONFIG_RTC_DRV_M48T35=m -CONFIG_RTC_DRV_M48T59=m -CONFIG_RTC_DRV_MSM6242=m -CONFIG_RTC_DRV_BQ4802=m -CONFIG_RTC_DRV_RP5C01=m -CONFIG_RTC_DRV_V3020=m -CONFIG_RTC_DRV_PCF50633=m - -# -# on-CPU RTC drivers -# -CONFIG_RTC_DRV_MV=y -CONFIG_DMADEVICES=y -# CONFIG_DMADEVICES_DEBUG is not set - -# -# DMA Devices -# -CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH=y -CONFIG_MV_XOR=y -CONFIG_TIMB_DMA=m -CONFIG_DMA_ENGINE=y - -# -# DMA Clients -# -# CONFIG_NET_DMA is not set -CONFIG_ASYNC_TX_DMA=y -# CONFIG_DMATEST is not set -# CONFIG_AUXDISPLAY is not set -CONFIG_UIO=m -CONFIG_UIO_CIF=m -CONFIG_UIO_PDRV=m -CONFIG_UIO_PDRV_GENIRQ=m -CONFIG_UIO_AEC=m -CONFIG_UIO_SERCOS3=m -CONFIG_UIO_PCI_GENERIC=m -CONFIG_UIO_NETX=m - -# -# Virtio drivers -# -# CONFIG_VIRTIO_PCI is not set -# CONFIG_VIRTIO_BALLOON is not set -# CONFIG_VIRTIO_MMIO is not set - -# -# Microsoft Hyper-V guest support -# -CONFIG_STAGING=y -# CONFIG_ET131X is not set -# CONFIG_USBIP_CORE is not set -# CONFIG_W35UND is not set -# CONFIG_PRISM2_USB is not set -# CONFIG_ECHO is not set -# CONFIG_ASUS_OLED is not set -# CONFIG_PANEL is not set -# CONFIG_R8187SE is not set -# CONFIG_RTL8192U is not set -# CONFIG_RTLLIB is not set -# CONFIG_R8712U is not set -# CONFIG_RTS_PSTOR is not set -CONFIG_RTS5139=m -# CONFIG_RTS5139_DEBUG is not set -# CONFIG_TRANZPORT is not set -# CONFIG_IDE_PHISON is not set -# CONFIG_LINE6_USB is not set -# CONFIG_USB_SERIAL_QUATECH2 is not set -# CONFIG_USB_SERIAL_QUATECH_USB2 is not set -# CONFIG_VT6655 is not set -# CONFIG_VT6656 is not set -# CONFIG_VME_BUS is not set -# CONFIG_DX_SEP is not set -# CONFIG_IIO is not set -# CONFIG_FB_SM7XX is not set -# CONFIG_CRYSTALHD is not set -# CONFIG_FB_XGI is not set -# CONFIG_USB_ENESTORAGE is not set -# CONFIG_BCM_WIMAX is not set -# CONFIG_FT1000 is not set - -# -# Speakup console speech -# -CONFIG_SPEAKUP=m -CONFIG_SPEAKUP_SYNTH_ACNTSA=m -CONFIG_SPEAKUP_SYNTH_ACNTPC=m -CONFIG_SPEAKUP_SYNTH_APOLLO=m -CONFIG_SPEAKUP_SYNTH_AUDPTR=m -CONFIG_SPEAKUP_SYNTH_BNS=m -CONFIG_SPEAKUP_SYNTH_DECTLK=m -CONFIG_SPEAKUP_SYNTH_DECEXT=m -# CONFIG_SPEAKUP_SYNTH_DECPC is not set -CONFIG_SPEAKUP_SYNTH_DTLK=m -CONFIG_SPEAKUP_SYNTH_KEYPC=m -CONFIG_SPEAKUP_SYNTH_LTLK=m -CONFIG_SPEAKUP_SYNTH_SOFT=m -CONFIG_SPEAKUP_SYNTH_SPKOUT=m -CONFIG_SPEAKUP_SYNTH_TXPRT=m -CONFIG_SPEAKUP_SYNTH_DUMMY=m -# CONFIG_TOUCHSCREEN_CLEARPAD_TM1217 is not set -# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set -# CONFIG_STAGING_MEDIA is not set - -# -# Android -# -# CONFIG_ANDROID is not set -# CONFIG_PHONE is not set -# CONFIG_USB_WPAN_HCD is not set - -# -# Hardware Spinlock drivers -# -CONFIG_CLKSRC_MMIO=y -CONFIG_IOMMU_SUPPORT=y - -# -# Remoteproc drivers (EXPERIMENTAL) -# - -# -# Rpmsg drivers (EXPERIMENTAL) -# -# CONFIG_VIRT_DRIVERS is not set -# CONFIG_PM_DEVFREQ is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT2_FS_POSIX_ACL=y -CONFIG_EXT2_FS_SECURITY=y -# CONFIG_EXT2_FS_XIP is not set -CONFIG_EXT3_FS=y -CONFIG_EXT3_DEFAULTS_TO_ORDERED=y -CONFIG_EXT3_FS_XATTR=y -CONFIG_EXT3_FS_POSIX_ACL=y -CONFIG_EXT3_FS_SECURITY=y -CONFIG_EXT4_FS=y -CONFIG_EXT4_FS_XATTR=y -CONFIG_EXT4_FS_POSIX_ACL=y -CONFIG_EXT4_FS_SECURITY=y -# CONFIG_EXT4_DEBUG is not set -CONFIG_JBD=y -# CONFIG_JBD_DEBUG is not set -CONFIG_JBD2=y -# CONFIG_JBD2_DEBUG is not set -CONFIG_FS_MBCACHE=y -CONFIG_REISERFS_FS=m -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set -CONFIG_REISERFS_FS_XATTR=y -CONFIG_REISERFS_FS_POSIX_ACL=y -CONFIG_REISERFS_FS_SECURITY=y -CONFIG_JFS_FS=m -CONFIG_JFS_POSIX_ACL=y -CONFIG_JFS_SECURITY=y -# CONFIG_JFS_DEBUG is not set -# CONFIG_JFS_STATISTICS is not set -CONFIG_XFS_FS=m -CONFIG_XFS_QUOTA=y -CONFIG_XFS_POSIX_ACL=y -CONFIG_XFS_RT=y -# CONFIG_XFS_DEBUG is not set -CONFIG_GFS2_FS=m -CONFIG_GFS2_FS_LOCKING_DLM=y -CONFIG_OCFS2_FS=m -CONFIG_OCFS2_FS_O2CB=m -CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m -CONFIG_OCFS2_FS_STATS=y -CONFIG_OCFS2_DEBUG_MASKLOG=y -# CONFIG_OCFS2_DEBUG_FS is not set -CONFIG_BTRFS_FS=m -CONFIG_BTRFS_FS_POSIX_ACL=y -# CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set -CONFIG_NILFS2_FS=m -CONFIG_FS_POSIX_ACL=y -CONFIG_EXPORTFS=y -CONFIG_FILE_LOCKING=y -CONFIG_FSNOTIFY=y -CONFIG_DNOTIFY=y -CONFIG_INOTIFY_USER=y -CONFIG_FANOTIFY=y -# CONFIG_FANOTIFY_ACCESS_PERMISSIONS is not set -CONFIG_QUOTA=y -CONFIG_QUOTA_NETLINK_INTERFACE=y -CONFIG_PRINT_QUOTA_WARNING=y -# CONFIG_QUOTA_DEBUG is not set -CONFIG_QUOTA_TREE=m -CONFIG_QFMT_V1=m -CONFIG_QFMT_V2=m -CONFIG_QUOTACTL=y -CONFIG_AUTOFS4_FS=m -CONFIG_FUSE_FS=m -CONFIG_CUSE=m -CONFIG_GENERIC_ACL=y - -# -# Caches -# -CONFIG_FSCACHE=m -# CONFIG_FSCACHE_STATS is not set -# CONFIG_FSCACHE_HISTOGRAM is not set -# CONFIG_FSCACHE_DEBUG is not set -# CONFIG_FSCACHE_OBJECT_LIST is not set -CONFIG_CACHEFILES=m -# CONFIG_CACHEFILES_DEBUG is not set -# CONFIG_CACHEFILES_HISTOGRAM is not set - -# -# CD-ROM/DVD Filesystems -# -CONFIG_ISO9660_FS=m -CONFIG_JOLIET=y -CONFIG_ZISOFS=y -CONFIG_UDF_FS=m -CONFIG_UDF_NLS=y - -# -# DOS/FAT/NT Filesystems -# -CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y -CONFIG_VFAT_FS=y -CONFIG_FAT_DEFAULT_CODEPAGE=437 -CONFIG_FAT_DEFAULT_IOCHARSET="utf8" -CONFIG_NTFS_FS=m -# CONFIG_NTFS_DEBUG is not set -CONFIG_NTFS_RW=y - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -CONFIG_PROC_SYSCTL=y -CONFIG_PROC_PAGE_MONITOR=y -CONFIG_SYSFS=y -CONFIG_TMPFS=y -CONFIG_TMPFS_POSIX_ACL=y -CONFIG_TMPFS_XATTR=y -# CONFIG_HUGETLB_PAGE is not set -CONFIG_CONFIGFS_FS=m -CONFIG_MISC_FILESYSTEMS=y -CONFIG_ADFS_FS=m -# CONFIG_ADFS_FS_RW is not set -CONFIG_AFFS_FS=m -CONFIG_ECRYPT_FS=m -CONFIG_HFS_FS=m -CONFIG_HFSPLUS_FS=m -CONFIG_BEFS_FS=m -# CONFIG_BEFS_DEBUG is not set -CONFIG_BFS_FS=m -CONFIG_EFS_FS=m -CONFIG_JFFS2_FS=y -CONFIG_JFFS2_FS_DEBUG=0 -CONFIG_JFFS2_FS_WRITEBUFFER=y -# CONFIG_JFFS2_FS_WBUF_VERIFY is not set -CONFIG_JFFS2_SUMMARY=y -CONFIG_JFFS2_FS_XATTR=y -CONFIG_JFFS2_FS_POSIX_ACL=y -CONFIG_JFFS2_FS_SECURITY=y -CONFIG_JFFS2_COMPRESSION_OPTIONS=y -CONFIG_JFFS2_ZLIB=y -CONFIG_JFFS2_LZO=y -CONFIG_JFFS2_RTIME=y -# CONFIG_JFFS2_RUBIN is not set -# CONFIG_JFFS2_CMODE_NONE is not set -CONFIG_JFFS2_CMODE_PRIORITY=y -# CONFIG_JFFS2_CMODE_SIZE is not set -# CONFIG_JFFS2_CMODE_FAVOURLZO is not set -CONFIG_UBIFS_FS=y -CONFIG_UBIFS_FS_XATTR=y -CONFIG_UBIFS_FS_ADVANCED_COMPR=y -CONFIG_UBIFS_FS_LZO=y -CONFIG_UBIFS_FS_ZLIB=y -# CONFIG_UBIFS_FS_DEBUG is not set -CONFIG_LOGFS=m -CONFIG_CRAMFS=m -CONFIG_SQUASHFS=m -CONFIG_SQUASHFS_XATTR=y -CONFIG_SQUASHFS_ZLIB=y -CONFIG_SQUASHFS_LZO=y -CONFIG_SQUASHFS_XZ=y -# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set -# CONFIG_SQUASHFS_EMBEDDED is not set -CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 -CONFIG_VXFS_FS=m -CONFIG_MINIX_FS=m -CONFIG_OMFS_FS=m -# CONFIG_HPFS_FS is not set -CONFIG_QNX4FS_FS=m -# CONFIG_QNX6FS_FS is not set -CONFIG_ROMFS_FS=m -# CONFIG_ROMFS_BACKED_BY_BLOCK is not set -# CONFIG_ROMFS_BACKED_BY_MTD is not set -CONFIG_ROMFS_BACKED_BY_BOTH=y -CONFIG_ROMFS_ON_BLOCK=y -CONFIG_ROMFS_ON_MTD=y -# CONFIG_PSTORE is not set -CONFIG_SYSV_FS=m -CONFIG_UFS_FS=m -# CONFIG_UFS_FS_WRITE is not set -# CONFIG_UFS_DEBUG is not set -CONFIG_EXOFS_FS=m -# CONFIG_EXOFS_DEBUG is not set -CONFIG_ORE=m -CONFIG_NETWORK_FILESYSTEMS=y -CONFIG_NFS_FS=m -CONFIG_NFS_V3=y -CONFIG_NFS_V3_ACL=y -CONFIG_NFS_V4=y -# CONFIG_NFS_V4_1 is not set -CONFIG_NFS_FSCACHE=y -# CONFIG_NFS_USE_LEGACY_DNS is not set -CONFIG_NFS_USE_KERNEL_DNS=y -CONFIG_NFSD=m -CONFIG_NFSD_V2_ACL=y -CONFIG_NFSD_V3=y -CONFIG_NFSD_V3_ACL=y -CONFIG_NFSD_V4=y -# CONFIG_NFSD_FAULT_INJECTION is not set -CONFIG_LOCKD=m -CONFIG_LOCKD_V4=y -CONFIG_NFS_ACL_SUPPORT=m -CONFIG_NFS_COMMON=y -CONFIG_SUNRPC=m -CONFIG_SUNRPC_GSS=m -CONFIG_RPCSEC_GSS_KRB5=m -# CONFIG_SUNRPC_DEBUG is not set -CONFIG_CEPH_FS=m -CONFIG_CIFS=m -# CONFIG_CIFS_STATS is not set -CONFIG_CIFS_WEAK_PW_HASH=y -CONFIG_CIFS_UPCALL=y -CONFIG_CIFS_XATTR=y -CONFIG_CIFS_POSIX=y -# CONFIG_CIFS_DEBUG2 is not set -CONFIG_CIFS_DFS_UPCALL=y -CONFIG_CIFS_FSCACHE=y -CONFIG_CIFS_ACL=y -# CONFIG_NCP_FS is not set -CONFIG_CODA_FS=m -# CONFIG_AFS_FS is not set -CONFIG_9P_FS=m -CONFIG_9P_FSCACHE=y -CONFIG_9P_FS_POSIX_ACL=y -CONFIG_NLS=y -CONFIG_NLS_DEFAULT="utf8" -CONFIG_NLS_CODEPAGE_437=m -CONFIG_NLS_CODEPAGE_737=m -CONFIG_NLS_CODEPAGE_775=m -CONFIG_NLS_CODEPAGE_850=m -CONFIG_NLS_CODEPAGE_852=m -CONFIG_NLS_CODEPAGE_855=m -CONFIG_NLS_CODEPAGE_857=m -CONFIG_NLS_CODEPAGE_860=m -CONFIG_NLS_CODEPAGE_861=m -CONFIG_NLS_CODEPAGE_862=m -CONFIG_NLS_CODEPAGE_863=m -CONFIG_NLS_CODEPAGE_864=m -CONFIG_NLS_CODEPAGE_865=m -CONFIG_NLS_CODEPAGE_866=m -CONFIG_NLS_CODEPAGE_869=m -CONFIG_NLS_CODEPAGE_936=m -CONFIG_NLS_CODEPAGE_950=m -CONFIG_NLS_CODEPAGE_932=m -CONFIG_NLS_CODEPAGE_949=m -CONFIG_NLS_CODEPAGE_874=m -CONFIG_NLS_ISO8859_8=m -CONFIG_NLS_CODEPAGE_1250=m -CONFIG_NLS_CODEPAGE_1251=m -CONFIG_NLS_ASCII=m -CONFIG_NLS_ISO8859_1=m -CONFIG_NLS_ISO8859_2=m -CONFIG_NLS_ISO8859_3=m -CONFIG_NLS_ISO8859_4=m -CONFIG_NLS_ISO8859_5=m -CONFIG_NLS_ISO8859_6=m -CONFIG_NLS_ISO8859_7=m -CONFIG_NLS_ISO8859_9=m -CONFIG_NLS_ISO8859_13=m -CONFIG_NLS_ISO8859_14=m -CONFIG_NLS_ISO8859_15=m -CONFIG_NLS_KOI8_R=m -CONFIG_NLS_KOI8_U=m -CONFIG_NLS_UTF8=m -CONFIG_DLM=m -CONFIG_DLM_DEBUG=y - -# -# Kernel hacking -# -CONFIG_PRINTK_TIME=y -CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 -CONFIG_ENABLE_WARN_DEPRECATED=y -CONFIG_ENABLE_MUST_CHECK=y -CONFIG_FRAME_WARN=1024 -# CONFIG_MAGIC_SYSRQ is not set -CONFIG_STRIP_ASM_SYMS=y -CONFIG_UNUSED_SYMBOLS=y -CONFIG_DEBUG_FS=y -# CONFIG_HEADERS_CHECK is not set -# CONFIG_DEBUG_SECTION_MISMATCH is not set -CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_SHIRQ is not set -CONFIG_LOCKUP_DETECTOR=y -# CONFIG_HARDLOCKUP_DETECTOR is not set -# CONFIG_BOOTPARAM_HARDLOCKUP_PANIC is not set -CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE=0 -# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set -CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 -CONFIG_DETECT_HUNG_TASK=y -CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 -# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set -CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 -# CONFIG_SCHED_DEBUG is not set -# CONFIG_SCHEDSTATS is not set -# CONFIG_TIMER_STATS is not set -# CONFIG_DEBUG_OBJECTS is not set -# CONFIG_SLUB_DEBUG_ON is not set -# CONFIG_SLUB_STATS is not set -# CONFIG_DEBUG_KMEMLEAK is not set -# CONFIG_DEBUG_RT_MUTEXES is not set -# CONFIG_RT_MUTEX_TESTER is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_MUTEXES is not set -# CONFIG_DEBUG_LOCK_ALLOC is not set -# CONFIG_PROVE_LOCKING is not set -# CONFIG_SPARSE_RCU_POINTER is not set -# CONFIG_LOCK_STAT is not set -# CONFIG_DEBUG_ATOMIC_SLEEP is not set -# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set -CONFIG_STACKTRACE=y -# CONFIG_DEBUG_STACK_USAGE is not set -# CONFIG_DEBUG_KOBJECT is not set -CONFIG_DEBUG_BUGVERBOSE=y -# CONFIG_DEBUG_INFO is not set -# CONFIG_DEBUG_VM is not set -# CONFIG_DEBUG_WRITECOUNT is not set -CONFIG_DEBUG_MEMORY_INIT=y -# CONFIG_DEBUG_LIST is not set -# CONFIG_TEST_LIST_SORT is not set -# CONFIG_DEBUG_SG is not set -# CONFIG_DEBUG_NOTIFIERS is not set -# CONFIG_DEBUG_CREDENTIALS is not set -# CONFIG_BOOT_PRINTK_DELAY is not set -# CONFIG_RCU_TORTURE_TEST 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 -# CONFIG_LKDTM is not set -# CONFIG_FAULT_INJECTION is not set -# CONFIG_LATENCYTOP is not set -# CONFIG_DEBUG_PAGEALLOC is not set -CONFIG_NOP_TRACER=y -CONFIG_HAVE_FUNCTION_TRACER=y -CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y -CONFIG_HAVE_DYNAMIC_FTRACE=y -CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y -CONFIG_HAVE_C_RECORDMCOUNT=y -CONFIG_RING_BUFFER=y -CONFIG_EVENT_TRACING=y -CONFIG_EVENT_POWER_TRACING_DEPRECATED=y -CONFIG_CONTEXT_SWITCH_TRACER=y -CONFIG_TRACING=y -CONFIG_GENERIC_TRACER=y -CONFIG_TRACING_SUPPORT=y -CONFIG_FTRACE=y -# CONFIG_FUNCTION_TRACER is not set -# CONFIG_IRQSOFF_TRACER is not set -# CONFIG_SCHED_TRACER is not set -CONFIG_BRANCH_PROFILE_NONE=y -# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set -# CONFIG_PROFILE_ALL_BRANCHES is not set -# CONFIG_STACK_TRACER is not set -CONFIG_BLK_DEV_IO_TRACE=y -# CONFIG_FTRACE_STARTUP_TEST is not set -# CONFIG_RING_BUFFER_BENCHMARK is not set -# CONFIG_FIREWIRE_OHCI_REMOTE_DMA is not set -# CONFIG_DYNAMIC_DEBUG is not set -# CONFIG_DMA_API_DEBUG is not set -# CONFIG_ATOMIC64_SELFTEST is not set -# CONFIG_ASYNC_RAID6_TEST is not set -# CONFIG_SAMPLES is not set -CONFIG_HAVE_ARCH_KGDB=y -# CONFIG_KGDB is not set -# CONFIG_TEST_KSTRTOX is not set -CONFIG_STRICT_DEVMEM=y -CONFIG_ARM_UNWIND=y -# CONFIG_DEBUG_USER is not set -CONFIG_DEBUG_LL=y -CONFIG_DEBUG_LL_UART_NONE=y -# CONFIG_DEBUG_ICEDCC is not set -# CONFIG_DEBUG_SEMIHOSTING is not set -CONFIG_EARLY_PRINTK=y - -# -# Security options -# -CONFIG_KEYS=y -# CONFIG_ENCRYPTED_KEYS is not set -CONFIG_KEYS_DEBUG_PROC_KEYS=y -# CONFIG_SECURITY_DMESG_RESTRICT is not set -CONFIG_SECURITY=y -CONFIG_SECURITYFS=y -CONFIG_SECURITY_NETWORK=y -CONFIG_SECURITY_NETWORK_XFRM=y -CONFIG_SECURITY_PATH=y -CONFIG_LSM_MMAP_MIN_ADDR=32768 -CONFIG_SECURITY_SELINUX=y -CONFIG_SECURITY_SELINUX_BOOTPARAM=y -CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=0 -CONFIG_SECURITY_SELINUX_DISABLE=y -CONFIG_SECURITY_SELINUX_DEVELOP=y -CONFIG_SECURITY_SELINUX_AVC_STATS=y -CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 -# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set -CONFIG_SECURITY_TOMOYO=y -CONFIG_SECURITY_TOMOYO_MAX_ACCEPT_ENTRY=2048 -CONFIG_SECURITY_TOMOYO_MAX_AUDIT_LOG=1024 -# CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER is not set -CONFIG_SECURITY_TOMOYO_POLICY_LOADER="/sbin/tomoyo-init" -CONFIG_SECURITY_TOMOYO_ACTIVATION_TRIGGER="/sbin/init" -# CONFIG_SECURITY_APPARMOR is not set -# CONFIG_SECURITY_YAMA is not set -# CONFIG_IMA is not set -# CONFIG_EVM is not set -CONFIG_DEFAULT_SECURITY_SELINUX=y -# CONFIG_DEFAULT_SECURITY_TOMOYO is not set -# CONFIG_DEFAULT_SECURITY_DAC is not set -CONFIG_DEFAULT_SECURITY="selinux" -CONFIG_XOR_BLOCKS=m -CONFIG_ASYNC_CORE=m -CONFIG_ASYNC_MEMCPY=m -CONFIG_ASYNC_XOR=m -CONFIG_ASYNC_PQ=m -CONFIG_ASYNC_RAID6_RECOV=m -CONFIG_CRYPTO=y - -# -# Crypto core or helper -# -CONFIG_CRYPTO_FIPS=y -CONFIG_CRYPTO_ALGAPI=y -CONFIG_CRYPTO_ALGAPI2=y -CONFIG_CRYPTO_AEAD=m -CONFIG_CRYPTO_AEAD2=y -CONFIG_CRYPTO_BLKCIPHER=m -CONFIG_CRYPTO_BLKCIPHER2=y -CONFIG_CRYPTO_HASH=y -CONFIG_CRYPTO_HASH2=y -CONFIG_CRYPTO_RNG=m -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_PCOMP=m -CONFIG_CRYPTO_PCOMP2=y -CONFIG_CRYPTO_MANAGER=y -CONFIG_CRYPTO_MANAGER2=y -# CONFIG_CRYPTO_USER is not set -# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set -CONFIG_CRYPTO_GF128MUL=m -CONFIG_CRYPTO_NULL=m -CONFIG_CRYPTO_WORKQUEUE=y -# CONFIG_CRYPTO_CRYPTD is not set -CONFIG_CRYPTO_AUTHENC=m -CONFIG_CRYPTO_TEST=m - -# -# Authenticated Encryption with Associated Data -# -CONFIG_CRYPTO_CCM=m -CONFIG_CRYPTO_GCM=m -CONFIG_CRYPTO_SEQIV=m - -# -# Block modes -# -CONFIG_CRYPTO_CBC=m -CONFIG_CRYPTO_CTR=m -CONFIG_CRYPTO_CTS=m -CONFIG_CRYPTO_ECB=m -CONFIG_CRYPTO_LRW=m -CONFIG_CRYPTO_PCBC=m -CONFIG_CRYPTO_XTS=m - -# -# Hash modes -# -CONFIG_CRYPTO_HMAC=m -CONFIG_CRYPTO_XCBC=m -CONFIG_CRYPTO_VMAC=m - -# -# Digest -# -CONFIG_CRYPTO_CRC32C=m -CONFIG_CRYPTO_GHASH=m -CONFIG_CRYPTO_MD4=m -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_MICHAEL_MIC=m -CONFIG_CRYPTO_RMD128=m -CONFIG_CRYPTO_RMD160=m -CONFIG_CRYPTO_RMD256=m -CONFIG_CRYPTO_RMD320=m -CONFIG_CRYPTO_SHA1=m -CONFIG_CRYPTO_SHA256=m -CONFIG_CRYPTO_SHA512=m -CONFIG_CRYPTO_TGR192=m -CONFIG_CRYPTO_WP512=m - -# -# Ciphers -# -CONFIG_CRYPTO_AES=m -CONFIG_CRYPTO_ANUBIS=m -CONFIG_CRYPTO_ARC4=m -CONFIG_CRYPTO_BLOWFISH=m -CONFIG_CRYPTO_BLOWFISH_COMMON=m -CONFIG_CRYPTO_CAMELLIA=m -CONFIG_CRYPTO_CAST5=m -CONFIG_CRYPTO_CAST6=m -CONFIG_CRYPTO_DES=m -CONFIG_CRYPTO_FCRYPT=m -CONFIG_CRYPTO_KHAZAD=m -CONFIG_CRYPTO_SALSA20=m -CONFIG_CRYPTO_SEED=m -CONFIG_CRYPTO_SERPENT=m -CONFIG_CRYPTO_TEA=m -CONFIG_CRYPTO_TWOFISH=m -CONFIG_CRYPTO_TWOFISH_COMMON=m - -# -# Compression -# -CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_ZLIB=m -CONFIG_CRYPTO_LZO=y - -# -# Random Number Generation -# -CONFIG_CRYPTO_ANSI_CPRNG=m -CONFIG_CRYPTO_USER_API=m -CONFIG_CRYPTO_USER_API_HASH=m -CONFIG_CRYPTO_USER_API_SKCIPHER=m -CONFIG_CRYPTO_HW=y -CONFIG_CRYPTO_DEV_MV_CESA=m -CONFIG_CRYPTO_DEV_HIFN_795X=m -CONFIG_CRYPTO_DEV_HIFN_795X_RNG=y -CONFIG_BINARY_PRINTF=y - -# -# Library routines -# -CONFIG_RAID6_PQ=m -CONFIG_BITREVERSE=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_IO=y -CONFIG_CRC_CCITT=m -CONFIG_CRC16=y -CONFIG_CRC_T10DIF=m -CONFIG_CRC_ITU_T=m -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=m -CONFIG_LIBCRC32C=m -# CONFIG_CRC8 is not set -CONFIG_AUDIT_GENERIC=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_LZO_COMPRESS=y -CONFIG_LZO_DECOMPRESS=y -CONFIG_XZ_DEC=y -CONFIG_XZ_DEC_X86=y -CONFIG_XZ_DEC_POWERPC=y -CONFIG_XZ_DEC_IA64=y -CONFIG_XZ_DEC_ARM=y -CONFIG_XZ_DEC_ARMTHUMB=y -CONFIG_XZ_DEC_SPARC=y -CONFIG_XZ_DEC_BCJ=y -# CONFIG_XZ_DEC_TEST is not set -CONFIG_DECOMPRESS_GZIP=y -CONFIG_DECOMPRESS_BZIP2=y -CONFIG_DECOMPRESS_LZMA=y -CONFIG_DECOMPRESS_XZ=y -CONFIG_DECOMPRESS_LZO=y -CONFIG_TEXTSEARCH=y -CONFIG_TEXTSEARCH_KMP=m -CONFIG_TEXTSEARCH_BM=m -CONFIG_TEXTSEARCH_FSM=m -CONFIG_BTREE=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y -CONFIG_HAS_DMA=y -CONFIG_DQL=y -CONFIG_NLATTR=y -CONFIG_GENERIC_ATOMIC64=y -CONFIG_LRU_CACHE=m -CONFIG_AVERAGE=y -# CONFIG_CORDIC is not set diff --git a/firmware/mrvl/helper_sd.bin b/firmware/mrvl/helper_sd.bin new file mode 100755 index 0000000..746ae0b Binary files /dev/null and b/firmware/mrvl/helper_sd.bin differ diff --git a/firmware/mrvl/sd8688.bin b/firmware/mrvl/sd8688.bin new file mode 100755 index 0000000..507b9c1 Binary files /dev/null and b/firmware/mrvl/sd8688.bin differ diff --git a/firmware/mrvl/sd8688_ap.bin b/firmware/mrvl/sd8688_ap.bin new file mode 100755 index 0000000..d3b042b Binary files /dev/null and b/firmware/mrvl/sd8688_ap.bin differ diff --git a/firmware/mrvl/sd8688_helper.bin b/firmware/mrvl/sd8688_helper.bin new file mode 100644 index 0000000..746ae0b Binary files /dev/null and b/firmware/mrvl/sd8688_helper.bin differ diff --git a/libertas_uap/Makefile b/libertas_uap/Makefile new file mode 100644 index 0000000..821f2a4 --- /dev/null +++ b/libertas_uap/Makefile @@ -0,0 +1,6 @@ +obj-$(CONFIG_LIBERTAS_UAP) += uap8xxx.o + +uap8xxx-y += uap_main.o uap_sdio_mmc.o +uap8xxx-$(CONFIG_PROC_FS) += uap_proc.o uap_debug.o + +EXTRA_CFLAGS += -DFPNUM='"52"' -DPXA3XX_DMA_ALIGN -DDEBUG_LEVEL1 diff --git a/libertas_uap/uap_debug.c b/libertas_uap/uap_debug.c new file mode 100644 index 0000000..e21c4aa --- /dev/null +++ b/libertas_uap/uap_debug.c @@ -0,0 +1,261 @@ +/** @file uap_debug.c + * @brief This file contains functions for debug proc file. + * + * Copyright (C) 2008-2009, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available along with the File in the gpl.txt file or by writing to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ +#ifdef CONFIG_PROC_FS +#include "uap_headers.h" + +/******************************************************** + Local Variables +********************************************************/ + +#define item_size(n) (sizeof ((uap_adapter *)0)->n) +#define item_addr(n) ((u32) &((uap_adapter *)0)->n) + +#define item_dbg_size(n) (sizeof (((uap_adapter *)0)->dbg.n)) +#define item_dbg_addr(n) ((u32) &(((uap_adapter *)0)->dbg.n)) + +#define item_dev_size(n) (sizeof ((uap_dev_t *)0)->n) +#define item_dev_addr(n) ((u32) &((uap_dev_t *)0)->n) + +/** MicroAp device offset */ +#define OFFSET_UAP_DEV 0x01 +/** Bluetooth adapter offset */ +#define OFFSET_UAP_ADAPTER 0x02 + +struct debug_data +{ + /** Name */ + char name[32]; + /** Size */ + u32 size; + /** Address */ + u32 addr; + /** Offset */ + u32 offset; + /** Flag */ + u32 flag; +}; + +/* To debug any member of uap_adapter, simply add one line here. + */ +static struct debug_data items[] = { + {"cmd_sent", item_dev_size(cmd_sent), 0, item_dev_addr(cmd_sent), + OFFSET_UAP_DEV}, + {"data_sent", item_dev_size(data_sent), 0, item_dev_addr(data_sent), + OFFSET_UAP_DEV}, + {"IntCounter", item_size(IntCounter), 0, item_addr(IntCounter), + OFFSET_UAP_ADAPTER}, + {"cmd_pending", item_size(cmd_pending), 0, item_addr(cmd_pending), + OFFSET_UAP_ADAPTER}, + {"num_cmd_h2c_fail", item_dbg_size(num_cmd_host_to_card_failure), 0, + item_dbg_addr(num_cmd_host_to_card_failure), OFFSET_UAP_ADAPTER}, + {"num_tx_h2c_fail", item_dbg_size(num_tx_host_to_card_failure), 0, + item_dbg_addr(num_tx_host_to_card_failure), OFFSET_UAP_ADAPTER}, + {"psmode", item_size(psmode), 0, item_addr(psmode), OFFSET_UAP_ADAPTER}, + {"ps_state", item_size(ps_state), 0, item_addr(ps_state), + OFFSET_UAP_ADAPTER}, +#ifdef DEBUG_LEVEL1 + {"drvdbg", sizeof(drvdbg), (u32) & drvdbg, 0, 0} +#endif +}; + +static int num_of_items = sizeof(items) / sizeof(items[0]); + +/******************************************************** + Global Variables +********************************************************/ + +/******************************************************** + Local Functions +********************************************************/ +/** + * @brief proc read function + * + * @param page pointer to buffer + * @param s read data starting position + * @param off offset + * @param cnt counter + * @param eof end of file flag + * @param data data to output + * @return number of output data + */ +static int +uap_debug_read(char *page, char **s, off_t off, int cnt, int *eof, void *data) +{ + int val = 0; + char *p = page; + int i; + + struct debug_data *d = (struct debug_data *) data; + + if (MODULE_GET == 0) + return UAP_STATUS_FAILURE; + + for (i = 0; i < num_of_items; i++) { + if (d[i].size == 1) + val = *((u8 *) d[i].addr); + else if (d[i].size == 2) + val = *((u16 *) d[i].addr); + else if (d[i].size == 4) + val = *((u32 *) d[i].addr); + + p += sprintf(p, "%s=%d\n", d[i].name, val); + } + MODULE_PUT; + return p - page; +} + +/** + * @brief proc write function + * + * @param f file pointer + * @param buf pointer to data buffer + * @param cnt data number to write + * @param data data to write + * @return number of data + */ +static int +uap_debug_write(struct file *f, const char *buf, unsigned long cnt, void *data) +{ + int r, i; + char *pdata; + char *p; + char *p0; + char *p1; + char *p2; + struct debug_data *d = (struct debug_data *) data; + + if (MODULE_GET == 0) + return UAP_STATUS_FAILURE; + + pdata = (char *) kmalloc(cnt, GFP_KERNEL); + if (pdata == NULL) { + MODULE_PUT; + return 0; + } + + if (copy_from_user(pdata, buf, cnt)) { + PRINTM(INFO, "Copy from user failed\n"); + kfree(pdata); + MODULE_PUT; + return 0; + } + + p0 = pdata; + for (i = 0; i < num_of_items; i++) { + do { + p = strstr(p0, d[i].name); + if (p == NULL) + break; + p1 = strchr(p, '\n'); + if (p1 == NULL) + break; + p0 = p1++; + p2 = strchr(p, '='); + if (!p2) + break; + p2++; + r = string_to_number(p2); + if (d[i].size == 1) + *((u8 *) d[i].addr) = (u8) r; + else if (d[i].size == 2) + *((u16 *) d[i].addr) = (u16) r; + else if (d[i].size == 4) + *((u32 *) d[i].addr) = (u32) r; + break; + } while (TRUE); + } + kfree(pdata); +#ifdef DEBUG_LEVEL1 + printk(KERN_ALERT "drvdbg = 0x%x\n", drvdbg); + printk(KERN_ALERT "INFO (%08lx) %s\n", DBG_INFO, + (drvdbg & DBG_INFO) ? "X" : ""); + printk(KERN_ALERT "WARN (%08lx) %s\n", DBG_WARN, + (drvdbg & DBG_WARN) ? "X" : ""); + printk(KERN_ALERT "ENTRY (%08lx) %s\n", DBG_ENTRY, + (drvdbg & DBG_ENTRY) ? "X" : ""); + printk(KERN_ALERT "CMD_D (%08lx) %s\n", DBG_CMD_D, + (drvdbg & DBG_CMD_D) ? "X" : ""); + printk(KERN_ALERT "DAT_D (%08lx) %s\n", DBG_DAT_D, + (drvdbg & DBG_DAT_D) ? "X" : ""); + printk(KERN_ALERT "CMND (%08lx) %s\n", DBG_CMND, + (drvdbg & DBG_CMND) ? "X" : ""); + printk(KERN_ALERT "DATA (%08lx) %s\n", DBG_DATA, + (drvdbg & DBG_DATA) ? "X" : ""); + printk(KERN_ALERT "ERROR (%08lx) %s\n", DBG_ERROR, + (drvdbg & DBG_ERROR) ? "X" : ""); + printk(KERN_ALERT "FATAL (%08lx) %s\n", DBG_FATAL, + (drvdbg & DBG_FATAL) ? "X" : ""); + printk(KERN_ALERT "MSG (%08lx) %s\n", DBG_MSG, + (drvdbg & DBG_MSG) ? "X" : ""); +#endif + MODULE_PUT; + return cnt; +} + +/******************************************************** + Global Functions +********************************************************/ +/** + * @brief create debug proc file + * + * @param priv pointer uap_private + * @param dev pointer net_device + * @return N/A + */ +void +uap_debug_entry(uap_private * priv, struct net_device *dev) +{ + int i; + struct proc_dir_entry *r; + + if (priv->proc_entry == NULL) + return; + + for (i = 0; i < num_of_items; i++) { + if (items[i].flag & OFFSET_UAP_ADAPTER) + items[i].addr = items[i].offset + (u32) priv->adapter; + if (items[i].flag & OFFSET_UAP_DEV) + items[i].addr = items[i].offset + (u32) & priv->uap_dev; + } + r = create_proc_entry("debug", 0644, priv->proc_entry); + if (r == NULL) + return; + + r->data = &items[0]; + r->read_proc = uap_debug_read; + r->write_proc = uap_debug_write; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) + r->owner = THIS_MODULE; +#endif +} + +/** + * @brief remove proc file + * + * @param priv pointer uap_private + * @return N/A + */ +void +uap_debug_remove(uap_private * priv) +{ + remove_proc_entry("debug", priv->proc_entry); +} + +#endif diff --git a/libertas_uap/uap_drv.h b/libertas_uap/uap_drv.h new file mode 100644 index 0000000..5aa009f --- /dev/null +++ b/libertas_uap/uap_drv.h @@ -0,0 +1,667 @@ +/** @file uap_drv.h + * @brief This file contains Linux OS related definitions and + * declarations, uAP driver + * + * Copyright (C) 2008-2009, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available along with the File in the gpl.txt file or by writing to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ + +#ifndef _UAP_DRV_H +#define _UAP_DRV_H + +/** Driver release version */ +#define DRIVER_VERSION "26146" + +/** True */ +#ifndef TRUE +#define TRUE 1 +#endif +/** False */ +#ifndef FALSE +#define FALSE 0 +#endif + +/** Bit definitions */ +#ifndef BIT +#define BIT(x) (1UL << (x)) +#endif + +/** Dma addresses are 32-bits wide. */ +#ifndef __ATTRIB_ALIGN__ +#define __ATTRIB_ALIGN__ __attribute__((aligned(4))) +#endif + +/** attribute pack */ +#ifndef __ATTRIB_PACK__ +#define __ATTRIB_PACK__ __attribute__ ((packed)) +#endif + +/** Debug Macro definition*/ +#ifdef DEBUG_LEVEL1 + +extern u32 drvdbg; + +/** Debug message control bit definition for drvdbg */ +/** Debug message */ +#define DBG_MSG BIT(0) +/** Debug fatal message */ +#define DBG_FATAL BIT(1) +/** Debug error message */ +#define DBG_ERROR BIT(2) +/** Debug data message */ +#define DBG_DATA BIT(3) +/** Debug command message */ +#define DBG_CMND BIT(4) + +/** Debug data */ +#define DBG_DAT_D BIT(16) +/** Debug command */ +#define DBG_CMD_D BIT(17) + +/** Debug entry */ +#define DBG_ENTRY BIT(28) +/** Debug warning */ +#define DBG_WARN BIT(29) +/** Debug info */ +#define DBG_INFO BIT(30) + +/** Print info */ +#define PRINTM_INFO(msg...) {if (drvdbg & DBG_INFO) printk(KERN_DEBUG msg);} +/** Print warn message */ +#define PRINTM_WARN(msg...) {if (drvdbg & DBG_WARN) printk(KERN_DEBUG msg);} +/** Print entry */ +#define PRINTM_ENTRY(msg...) {if (drvdbg & DBG_ENTRY) printk(KERN_DEBUG msg);} +/** Print cmd_d */ +#define PRINTM_CMD_D(msg...) {if (drvdbg & DBG_CMD_D) printk(KERN_DEBUG msg);} +/** Print data_d */ +#define PRINTM_DAT_D(msg...) {if (drvdbg & DBG_DAT_D) printk(KERN_DEBUG msg);} +/** Print command */ +#define PRINTM_CMND(msg...) {if (drvdbg & DBG_CMND) printk(KERN_DEBUG msg);} +/** Print data */ +#define PRINTM_DATA(msg...) {if (drvdbg & DBG_DATA) printk(KERN_DEBUG msg);} +/** Print error message */ +#define PRINTM_ERROR(msg...) {if (drvdbg & DBG_ERROR) printk(KERN_DEBUG msg);} +/** Print fatal message */ +#define PRINTM_FATAL(msg...) {if (drvdbg & DBG_FATAL) printk(KERN_DEBUG msg);} +/** Print message */ +#define PRINTM_MSG(msg...) {if (drvdbg & DBG_MSG) printk(KERN_ALERT msg);} +/** Print level */ +#define PRINTM(level,msg...) PRINTM_##level(msg) + +#else + +#define PRINTM(level,msg...) do {} while (0) + +#endif /* DEBUG_LEVEL1 */ + +/** Wait until a condition becomes true */ +#define ASSERT(cond) \ +do { \ + if (!(cond)) \ + PRINTM(INFO, "ASSERT: %s, %s:%i\n", \ + __FUNCTION__, __FILE__, __LINE__); \ +} while(0) + +/** Log enrty point for debugging */ +#define ENTER() PRINTM(ENTRY, "Enter: %s, %s:%i\n", __FUNCTION__, \ + __FILE__, __LINE__) +/** Log exit point for debugging */ +#define LEAVE() PRINTM(ENTRY, "Leave: %s, %s:%i\n", __FUNCTION__, \ + __FILE__, __LINE__) + +#ifdef DEBUG_LEVEL1 +/** Dump buffer length */ +#define DBG_DUMP_BUF_LEN 64 +/** Maximum dump per line */ +#define MAX_DUMP_PER_LINE 16 +/** Data dump length */ +#define DATA_DUMP_LEN 32 + +static inline void +hexdump(char *prompt, u8 * buf, int len) +{ + int i; + char dbgdumpbuf[DBG_DUMP_BUF_LEN]; + char *ptr = dbgdumpbuf; + + printk(KERN_DEBUG "%s:\n", prompt); + for (i = 1; i <= len; i++) { + ptr += sprintf(ptr, "%02x ", *buf); + buf++; + if (i % MAX_DUMP_PER_LINE == 0) { + *ptr = 0; + printk(KERN_DEBUG "%s\n", dbgdumpbuf); + ptr = dbgdumpbuf; + } + } + if (len % MAX_DUMP_PER_LINE) { + *ptr = 0; + printk(KERN_DEBUG "%s\n", dbgdumpbuf); + } +} + +/** Debug command */ +#define DBG_HEXDUMP_CMD_D(x,y,z) {if (drvdbg & DBG_CMD_D) hexdump(x,y,z);} +/** Debug data */ +#define DBG_HEXDUMP_DAT_D(x,y,z) {if (drvdbg & DBG_DAT_D) hexdump(x,y,z);} +/** Debug hexdump */ +#define DBG_HEXDUMP(level,x,y,z) DBG_HEXDUMP_##level(x,y,z) +/** hexdump */ +#define HEXDUMP(x,y,z) {if (drvdbg & DBG_INFO) hexdump(x,y,z);} +#else +/** Do nothing since debugging is not turned on */ +#define DBG_HEXDUMP(level,x,y,z) do {} while (0) +/** Do nothing since debugging is not turned on */ +#define HEXDUMP(x,y,z) do {} while (0) +#endif + +/** + * Typedefs + */ +/** Unsigned char */ +typedef u8 BOOLEAN; + +/* + * OS macro definitions + */ +/** OS macro to get time */ +#define os_time_get() jiffies + +/** OS macro to update transfer start time */ +#define UpdateTransStart(dev) { \ + dev->trans_start = jiffies; \ +} + +/** Try to get a reference to the module */ +#define MODULE_GET try_module_get(THIS_MODULE) +/** Decrease module reference count */ +#define MODULE_PUT module_put(THIS_MODULE) + +/** OS macro to initialize semaphore */ +#define OS_INIT_SEMAPHORE(x) sema_init(x,1) +/** OS macro to acquire blocking semaphore */ +#define OS_ACQ_SEMAPHORE_BLOCK(x) down_interruptible(x) +/** OS macro to acquire non-blocking semaphore */ +#define OS_ACQ_SEMAPHORE_NOBLOCK(x) down_trylock(x) +/** OS macro to release semaphore */ +#define OS_REL_SEMAPHORE(x) up(x) + +static inline void +os_sched_timeout(u32 millisec) +{ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout((millisec * HZ) / 1000); +} + +/** Maximum size of ethernet packet */ +#define MRVDRV_MAXIMUM_ETH_PACKET_SIZE 1514 + +/** Maximum size of multicast list */ +#define MRVDRV_MAX_MULTICAST_LIST_SIZE 32 + +/** Find minimum */ +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +/** Find maximum */ +#ifndef MAX +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif + +/** Find number of elements */ +#ifndef NELEMENTS +#define NELEMENTS(x) (sizeof(x)/sizeof(x[0])) +#endif + +/** Buffer Constants */ + +/** Size of command buffer */ +#define MRVDRV_SIZE_OF_CMD_BUFFER (2 * 1024) + +/** Length of device length */ +#define DEV_NAME_LEN 32 + +/** Length of ethernet address */ +#ifndef ETH_ALEN +#define ETH_ALEN 6 +#endif + +/** Default watchdog timeout */ +#define MRVDRV_DEFAULT_WATCHDOG_TIMEOUT (2 * HZ) + +/** Success */ +#define UAP_STATUS_SUCCESS (0) +/** Failure */ +#define UAP_STATUS_FAILURE (-1) +/** Not accepted */ +#define UAP_STATUS_NOT_ACCEPTED (-2) + +/** Max loop count (* 100ms) for waiting device ready at init time */ +#define MAX_WAIT_DEVICE_READY_COUNT 50 + +/** Tx high watermark. Stop Tx queue after this is crossed */ +#define TX_HIGH_WATERMARK 4 +/** Tx low watermark. Restart Tx queue after this is crossed */ +#define TX_LOW_WATERMARK 2 + +/** Netlink protocol number */ +#define NETLINK_MARVELL (MAX_LINKS - 1) +/** Netlink maximum payload size */ +#define NL_MAX_PAYLOAD 1024 +/** Netlink multicast group number */ +#define NL_MULTICAST_GROUP 1 + +/** 20 seconds */ +#define MRVDRV_TIMER_20S 20000 + +/** Host Command option for wait till Send */ +#define HostCmd_OPTION_WAITFORSEND 0x0001 +/** Host Command option for wait for RSP */ +#define HostCmd_OPTION_WAITFORRSP 0x0002 +/** Host Command option for wait for RSP or Timeout */ +#define HostCmd_OPTION_WAITFORRSP_TIMEOUT 0x0003 +/** Host Command option for wait for RSP of sleep confirm */ +#define HostCmd_OPTION_WAITFORRSP_SLEEPCONFIRM 0x0004 + +/** Sleep until a condition gets true or a timeout elapses */ +#define os_wait_interruptible_timeout(waitq, cond, timeout) \ + wait_event_interruptible_timeout(waitq, cond, ((timeout) * HZ / 1000)) + +/** Private command ID to Host command */ +#define UAPHOSTCMD (SIOCDEVPRIVATE + 1) + +/** Private command ID to Power Mode */ +#define UAP_POWER_MODE (SIOCDEVPRIVATE + 3) +/** sleep_param */ +typedef struct _ps_sleep_param +{ + /** control bitmap */ + u32 ctrl_bitmap; + /** minimum sleep period (micro second) */ + u32 min_sleep; + /** maximum sleep period (micro second) */ + u32 max_sleep; +} ps_sleep_param; + +/** inactivity sleep_param */ +typedef struct _inact_sleep_param +{ + /** inactivity timeout (micro second) */ + u32 inactivity_to; + /** miniumu awake period (micro second) */ + u32 min_awake; + /** maximum awake period (micro second) */ + u32 max_awake; +} inact_sleep_param; + +/** flag for ps mode */ +#define PS_FLAG_PS_MODE 1 +/** flag for sleep param */ +#define PS_FLAG_SLEEP_PARAM 2 +/** flag for inactivity sleep param */ +#define PS_FLAG_INACT_SLEEP_PARAM 4 + +/** Disable power mode */ +#define PS_MODE_DISABLE 0 +/** Enable periodic dtim ps */ +#define PS_MODE_PERIODIC_DTIM 1 +/** Enable inactivity ps */ +#define PS_MODE_INACTIVITY 2 + +/** sleep parameter */ +#define SLEEP_PARAMETER 1 +/** inactivity sleep parameter */ +#define INACTIVITY_SLEEP_PARAMETER 2 +/** ps_mgmt */ +typedef struct _ps_mgmt +{ + /** flags for valid field */ + u16 flags; + /** power mode */ + u16 ps_mode; + /** sleep param */ + ps_sleep_param sleep_param; + /** inactivity sleep param */ + inact_sleep_param inact_param; +} ps_mgmt; + +/** Semaphore structure */ +typedef struct semaphore SEMAPHORE; + +/** Global Varibale Declaration */ +/** Private data structure of the device */ +typedef struct _uap_private uap_private; +/** Adapter data structure of the device */ +typedef struct _uap_adapter uap_adapter; +/** private structure */ +extern uap_private *uappriv; + +/** ENUM definition*/ + +/** Hardware status codes */ +typedef enum _HARDWARE_STATUS +{ + HWReady, + HWInitializing, + HWReset, + HWClosing, + HWNotReady +} HARDWARE_STATUS; + +/** info for debug purpose */ +typedef struct _uap_dbg +{ + /** Number of host to card command failures */ + u32 num_cmd_host_to_card_failure; + /** Number of host to card Tx failures */ + u32 num_tx_host_to_card_failure; +} uap_dbg; + +/** Set thread state */ +#define OS_SET_THREAD_STATE(x) set_current_state(x) + +typedef struct +{ + /** Task */ + struct task_struct *task; + /** Queue */ + wait_queue_head_t waitQ; + /** PID */ + pid_t pid; + /** Private structure */ + void *priv; +} uap_thread; + +static inline void +uap_activate_thread(uap_thread * thr) +{ + /** Record the thread pid */ + thr->pid = current->pid; + + /** Initialize the wait queue */ + init_waitqueue_head(&thr->waitQ); +} + +static inline void +uap_deactivate_thread(uap_thread * thr) +{ + thr->pid = 0; + return; +} + +static inline void +uap_create_thread(int (*uapfunc) (void *), uap_thread * thr, char *name) +{ + thr->task = kthread_run(uapfunc, thr, "%s", name); +} + +static inline int +uap_terminate_thread(uap_thread * thr) +{ + /* Check if the thread is active or not */ + if (!thr->pid) + return -1; + kthread_stop(thr->task); + return 0; +} + +/** Data structure for the Marvell uAP device */ +typedef struct _uap_dev +{ + /** device name */ + char name[DEV_NAME_LEN]; + /** card pointer */ + void *card; + /** IO port */ + u32 ioport; + /** Rx unit */ + u8 rx_unit; + /** Data sent: + TRUE - Data is sent to fw, no Tx Done received + FALSE - Tx done received for previous Tx */ + BOOLEAN data_sent; + /** CMD sent: + TRUE - CMD is sent to fw, no CMD Done received + FALSE - CMD done received for previous CMD */ + BOOLEAN cmd_sent; + /** netdev pointer */ + struct net_device *netdev; +} uap_dev_t, *puap_dev_t; + +/** Private structure for the MV device */ +struct _uap_private +{ + /** Device open */ + int open; + + /** Device adapter structure */ + uap_adapter *adapter; + /** Device structure */ + uap_dev_t uap_dev; + + /** Net device statistics structure */ + struct net_device_stats stats; + + /** Number of Tx timeouts */ + u32 num_tx_timeout; + + /** Media connection status */ + BOOLEAN MediaConnected; + +#ifdef CONFIG_PROC_FS + struct proc_dir_entry *proc_uap; + struct proc_dir_entry *proc_entry; +#endif /* CONFIG_PROC_FS */ + + /** Firmware helper */ + const struct firmware *fw_helper; + /** Firmware */ + const struct firmware *firmware; + /** Hotplug device */ + struct device *hotplug_device; + /** thread to service interrupts */ + uap_thread MainThread; + /** Driver lock */ + spinlock_t driver_lock; + /** Driver lock flags */ + ulong driver_flags; + +}; + +/** PS_CMD_ConfirmSleep */ +typedef struct _PS_CMD_ConfirmSleep +{ + /** SDIO Length */ + u16 SDLen; + /** SDIO Type */ + u16 SDType; + /** Command */ + u16 Command; + /** Size */ + u16 Size; + /** Sequence number */ + u16 SeqNum; + /** Result */ + u16 Result; +} __ATTRIB_PACK__ PS_CMD_ConfirmSleep, *PPS_CMD_ConfirmSleep; + +/** Wlan Adapter data structure*/ +struct _uap_adapter +{ + /** Power save confirm sleep command */ + PS_CMD_ConfirmSleep PSConfirmSleep; + /** Device status */ + HARDWARE_STATUS HardwareStatus; + /** Interrupt counter */ + u32 IntCounter; + /** Tx packet queue */ + struct sk_buff_head tx_queue; + /** Cmd packet queue */ + struct sk_buff_head cmd_queue; + /** Command sequence number */ + u16 SeqNum; + /** Command buffer */ + u8 *CmdBuf; + /** cmd pending flag */ + u8 cmd_pending; + /** cmd wait option */ + u8 cmd_wait_option; + /** Command buffer length */ + u32 CmdSize; + /** Command wait queue */ + wait_queue_head_t cmdwait_q __ATTRIB_ALIGN__; + /** Command wait queue state flag */ + u8 CmdWaitQWoken; + /** PnP support */ + BOOLEAN SurpriseRemoved; + /** Debug */ + uap_dbg dbg; + /** Netlink kernel socket */ + struct sock *nl_sk; + /** Semaphore for CMD */ + SEMAPHORE CmdSem; + /** Power Save mode */ + u8 psmode; + /** Power Save state */ + u8 ps_state; + /** Number of wakeup tries */ + u32 WakeupTries; +}; + +static inline int +os_upload_rx_packet(uap_private * priv, struct sk_buff *skb) +{ + skb->dev = priv->uap_dev.netdev; + skb->protocol = eth_type_trans(skb, priv->uap_dev.netdev); + skb->ip_summed = CHECKSUM_UNNECESSARY; + if (in_interrupt()) + netif_rx(skb); + else + netif_rx_ni(skb); + return 0; +} + +/* + * netif carrier_on/off and start(wake)/stop_queue handling + */ +static inline void +os_carrier_on(uap_private * priv) +{ + if (!netif_carrier_ok(priv->uap_dev.netdev) && + (priv->MediaConnected == TRUE)) { + netif_carrier_on(priv->uap_dev.netdev); + } +} + +static inline void +os_carrier_off(uap_private * priv) +{ + if (netif_carrier_ok(priv->uap_dev.netdev)) { + netif_carrier_off(priv->uap_dev.netdev); + } +} + +static inline void +os_start_queue(uap_private * priv) +{ + if (netif_queue_stopped(priv->uap_dev.netdev) && + (priv->MediaConnected == TRUE)) { + netif_wake_queue(priv->uap_dev.netdev); + } +} + +static inline void +os_stop_queue(uap_private * priv) +{ + if (!netif_queue_stopped(priv->uap_dev.netdev)) { + netif_stop_queue(priv->uap_dev.netdev); + } +} + +/** Interface specific header */ +#define INTF_HEADER_LEN 4 + +/** headroom alignment for tx packet */ +#define HEADER_ALIGNMENT 8 + +/** The number of times to try when polling for status bits */ +#define MAX_POLL_TRIES 100 + +/** Length of SNAP header */ +#define MRVDRV_SNAP_HEADER_LEN 8 + +/** Extra length of Tx packet buffer */ +#define EXTRA_LEN 36 + +/** Buffer size for ethernet Tx packets */ +#define MRVDRV_ETH_TX_PACKET_BUFFER_SIZE \ + (ETH_FRAME_LEN + sizeof(TxPD) + EXTRA_LEN) + +/** Buffer size for ethernet Rx packets */ +#define MRVDRV_ETH_RX_PACKET_BUFFER_SIZE \ + (ETH_FRAME_LEN + sizeof(RxPD) \ + + MRVDRV_SNAP_HEADER_LEN + EXTRA_LEN) + +/** Packet type: data, command & event */ +typedef enum _mv_type +{ + MV_TYPE_DAT = 0, + MV_TYPE_CMD = 1, + MV_TYPE_EVENT = 3 +} mv_type; + +/** Disable interrupt */ +#define OS_INT_DISABLE spin_lock_irqsave(&priv->driver_lock, priv->driver_flags) +/** Enable interrupt */ +#define OS_INT_RESTORE spin_unlock_irqrestore(&priv->driver_lock, priv->driver_flags) + +int uap_process_rx_packet(uap_private * priv, struct sk_buff *skb); +void uap_interrupt(uap_private * priv); +uap_private *uap_add_card(void *card); +int uap_remove_card(void *card); +int uap_process_event(uap_private * priv, u8 * payload, uint len); +int uap_soft_reset(uap_private * priv); +int uap_process_sleep_confirm_resp(uap_private * priv, u8 * resp, int resp_len); + +#ifdef CONFIG_PROC_FS +/** The proc fs interface */ +void uap_proc_entry(uap_private * priv, struct net_device *dev); +void uap_proc_remove(uap_private * priv); +int string_to_number(char *s); +void uap_debug_entry(uap_private * priv, struct net_device *dev); +void uap_debug_remove(uap_private * priv); +#endif /* CONFIG_PROC_FS */ + +int sbi_register(void); + +void sbi_unregister(void); +int sbi_register_dev(uap_private * priv); +int sbi_unregister_dev(uap_private * priv); +int sbi_prog_fw_w_helper(uap_private *); + +int sbi_host_to_card(uap_private * priv, u8 * payload, u16 nb); +int sbi_enable_host_int(uap_private * priv); +int sbi_disable_host_int(uap_private * priv); + +int sbi_get_int_status(uap_private * priv, u8 * ireg); +/** Check firmware status */ +int sbi_check_fw_status(uap_private *, int); +int sbi_prog_helper(uap_private *); + +int sbi_wakeup_firmware(uap_private * priv); + +#endif /* _UAP_DRV_H */ diff --git a/libertas_uap/uap_fw.h b/libertas_uap/uap_fw.h new file mode 100644 index 0000000..23a40d6 --- /dev/null +++ b/libertas_uap/uap_fw.h @@ -0,0 +1,359 @@ +/** @file uap_fw.h + * + * @brief This file contains firmware specific defines. + * + * Copyright (C) 2008-2009, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available along with the File in the gpl.txt file or by writing to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ +/******************************************************** +Change log: + 02/26/08: Initial creation +********************************************************/ + +#ifndef _UAP_FW_H +#define _UAP_FW_H + +/** uap upload size */ +#define UAP_UPLD_SIZE 2312 +/** Packet type Micro AP */ +#define PKT_TYPE_MICROAP 1 +/** Packet type client */ +#define PKT_TYPE_CLIENT 0 + +/** TxPD descriptor */ +typedef struct _TxPD +{ + /** Bss Type */ + u8 BssType; + /** Bss num */ + u8 BssNum; + /** Tx packet length */ + u16 TxPktLength; + /** Tx packet offset */ + u16 TxPktOffset; + /** Tx packet type */ + u16 TxPktType; + /** Tx Control */ + u32 TxControl; + /** reserved */ + u32 reserved[2]; +} __ATTRIB_PACK__ TxPD, *PTxPD; + +/** RxPD Descriptor */ +typedef struct _RxPD +{ + /** Bss Type */ + u8 BssType; + /** Bss Num */ + u8 BssNum; + /** Tx packet length */ + u16 RxPktLength; + /** Tx packet offset */ + u16 RxPktOffset; +} __ATTRIB_PACK__ RxPD, *PRxPD; + +#ifdef BIG_ENDIAN +/** Convert from 16 bit little endian format to CPU format */ +#define uap_le16_to_cpu(x) le16_to_cpu(x) +/** Convert from 32 bit little endian format to CPU format */ +#define uap_le32_to_cpu(x) le32_to_cpu(x) +/** Convert from 64 bit little endian format to CPU format */ +#define uap_le64_to_cpu(x) le64_to_cpu(x) +/** Convert to 16 bit little endian format from CPU format */ +#define uap_cpu_to_le16(x) cpu_to_le16(x) +/** Convert to 32 bit little endian format from CPU format */ +#define uap_cpu_to_le32(x) cpu_to_le32(x) +/** Convert to 64 bit little endian format from CPU format */ +#define uap_cpu_to_le64(x) cpu_to_le64(x) + +/** Convert TxPD to little endian format from CPU format */ +#define endian_convert_TxPD(x); \ + { \ + (x)->TxPktLength = uap_cpu_to_le16((x)->TxPktLength); \ + (x)->TxPktOffset = uap_cpu_to_le32((x)->TxPktOffset); \ + (x)->TxControl = uap_cpu_to_le32((x)->TxControl); \ + (x)->TxPktType = uap_cpu_to_le32((x)->TxPktType); \ + } + +/** Convert RxPD from little endian format to CPU format */ +#define endian_convert_RxPD(x); \ + { \ + (x)->RxPktLength = uap_le16_to_cpu((x)->RxPktLength); \ + (x)->RxPktOffset = uap_le32_to_cpu((x)->RxPktOffset); \ + } +#else /* BIG_ENDIAN */ +/** Do nothing */ +#define uap_le16_to_cpu(x) x +/** Do nothing */ +#define uap_le32_to_cpu(x) x +/** Do nothing */ +#define uap_le64_to_cpu(x) x +/** Do nothing */ +#define uap_cpu_to_le16(x) x +/** Do nothing */ +#define uap_cpu_to_le32(x) x +/** Do nothing */ +#define uap_cpu_to_le64(x) x + +/** Do nothing */ +#define endian_convert_TxPD(x) +/** Do nothing */ +#define endian_convert_RxPD(x) +#endif /* BIG_ENDIAN */ + +/** Host Command ID : Function initialization */ +#define HostCmd_CMD_FUNC_INIT 0x00a9 +/** Host Command ID : Function shutdown */ +#define HostCmd_CMD_FUNC_SHUTDOWN 0x00aa + +/** Host Command id: SYS_INFO */ +#define HOST_CMD_APCMD_SYS_INFO 0x00ae +/** Host Command id: SYS_RESET */ +#define HOST_CMD_APCMD_SYS_RESET 0x00af +/** Host Command id: SYS_CONFIGURE */ +#define HOST_CMD_APCMD_SYS_CONFIGURE 0x00b0 +/** Host Command id: BSS_START */ +#define HOST_CMD_APCMD_BSS_START 0x00b1 +/** Host Command id: SYS_STOP */ +#define HOST_CMD_APCMD_BSS_STOP 0x00b2 +/** Host Command id: STA_LIST */ +#define HOST_CMD_APCMD_STA_LIST 0x00b3 +/** Host Command id: STA_FILTER_TABLE */ +#define HOST_CMD_APCMD_STA_FILTER_TABLE 0x00b4 +/** Host Command id: STA_DEAUTH */ +#define HOST_CMD_APCMD_STA_DEAUTH 0x00b5 +/** Host Command id: SOFT_RESET */ +#define HOST_CMD_APCMD_SOFT_RESET 0x00d5 +/** Host Command id: POWER_MGMT_EXT */ +#define HOST_CMD_POWER_MGMT_EXT 0x00ef +/** Host Command id: SLEEP_CONFIRM*/ +#define HOST_CMD_SLEEP_CONFIRM 0x00d8 + +/** TLV type : SSID */ +#define TLV_TYPE_SSID 0x0000 +/** TLV type : Rates */ +#define TLV_TYPE_RATES 0x0001 +/** TLV type : PHY DS */ +#define TLV_TYPE_PHY_DS 0x0003 + +/** TLV Id : Base id */ +#define PROPRIETARY_TLV_BASE_ID 0x0100 +/** TLV Id : AP_MAC_ADDRESS */ +#define MRVL_AP_MAC_ADDRESS_TLV_ID (PROPRIETARY_TLV_BASE_ID + 43) +/** TLV Id : Beacon period */ +#define MRVL_BEACON_PERIOD_TLV_ID (PROPRIETARY_TLV_BASE_ID + 44) +/** TLV Id : Dtim period */ +#define MRVL_DTIM_PERIOD_TLV_ID (PROPRIETARY_TLV_BASE_ID + 45) +/** TLV Id : Basic rates */ +#define MRVL_BASIC_RATES_TLV_ID (PROPRIETARY_TLV_BASE_ID + 46) +/** TLV Id : Tx Power */ +#define MRVL_TX_POWER_TLV_ID (PROPRIETARY_TLV_BASE_ID + 47) +/** TLV Id : Broadcast SSID control */ +#define MRVL_BCAST_SSID_CTL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 48) +/** TLV Id : Preamble control */ +#define MRVL_PREAMBLE_CTL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 49) +/** TLV Id : Antenna control */ +#define MRVL_ANTENNA_CTL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 50) +/** TLV Id : RTS threshold */ +#define MRVL_RTS_THRESHOLD_TLV_ID (PROPRIETARY_TLV_BASE_ID + 51) +/** TLV Id : Radio control */ +#define MRVL_RADIO_CTL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 52) +/** TLV Id : TX data rate */ +#define MRVL_TX_DATA_RATE_TLV_ID (PROPRIETARY_TLV_BASE_ID + 53) +/** TLV Id : Packet forward control */ +#define MRVL_PKT_FWD_CTL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 54) +/** TLV Id : STA info */ +#define MRVL_STA_INFO_TLV_ID (PROPRIETARY_TLV_BASE_ID + 55) +/** TLV Id : STA MAC address filter */ +#define MRVL_STA_MAC_ADDR_FILTER_TLV_ID (PROPRIETARY_TLV_BASE_ID + 56) +/** TLV Id : STA ageout timer */ +#define MRVL_STA_AGEOUT_TIMER_TLV_ID (PROPRIETARY_TLV_BASE_ID + 57) +/** TLV Id : Security config */ +#define MRVL_SECURITY_CFG_TLV_ID (PROPRIETARY_TLV_BASE_ID + 58) +/** TLV Id : WEP KEY */ +#define MRVL_WEP_KEY_TLV_ID (PROPRIETARY_TLV_BASE_ID + 59) +/** TLV Id : WPA Passphrase */ +#define MRVL_WPA_PASSPHRASE_TLV_ID (PROPRIETARY_TLV_BASE_ID + 60) + +/** Action get */ +#define ACTION_GET 0 +/** Action set */ +#define ACTION_SET 1 +/** Length of ethernet address */ +#ifndef ETH_ALEN +#define ETH_ALEN 6 +#endif + +/** HostCmd_DS_GEN */ +typedef struct +{ + /** Command */ + u16 Command; + /** Size */ + u16 Size; + /** Sequence number */ + u16 SeqNum; + /** Result */ + u16 Result; +} __ATTRIB_PACK__ HostCmd_DS_GEN; + +/** Size of HostCmd_DS_GEN */ +#define S_DS_GEN sizeof(HostCmd_DS_GEN) + +/** _HostCmd_HEADER*/ +typedef struct +{ + /** Command Header : Command */ + u16 Command; + /** Command Header : Size */ + u16 Size; +} __ATTRIB_PACK__ HostCmd_HEADER; + +/** HostCmd_SYS_CONFIG */ +typedef struct _HostCmd_SYS_CONFIG +{ + /** CMD Action GET/SET*/ + u16 Action; + /** Tlv buffer */ + u8 TlvBuffer[0]; +} __ATTRIB_PACK__ HostCmd_SYS_CONFIG; + +/** HostCmd_DS_POWER_MGMT_EXT */ +typedef struct _HostCmd_DS_POWER_MGMT_EXT +{ + /** CMD Action Get/Set*/ + u16 action; + /** power mode */ + u16 power_mode; +} __ATTRIB_PACK__ HostCmd_DS_POWER_MGMT_EXT; + +/** _HostCmd_DS_COMMAND*/ +typedef struct _HostCmd_DS_COMMAND +{ + + /** Command Header : Command */ + u16 Command; + /** Command Header : Size */ + u16 Size; + /** Command Header : Sequence number */ + u16 SeqNum; + /** Command Header : Result */ + u16 Result; + /** Command Body */ + union + { + HostCmd_SYS_CONFIG sys_config; + HostCmd_DS_POWER_MGMT_EXT pm_cfg; + + } params; +} __ATTRIB_PACK__ HostCmd_DS_COMMAND; + +/** MrvlIEtypesHeader_*/ +typedef struct _MrvlIEtypesHeader +{ + /** Header type */ + u16 Type; + /** Header length */ + u16 Len; +} __ATTRIB_PACK__ MrvlIEtypesHeader_t; + +/** MrvlIEtypes_Data_t */ +typedef struct _MrvlIEtypes_Data_t +{ + /** Header */ + MrvlIEtypesHeader_t Header; + /** Data */ + u8 Data[1]; +} __ATTRIB_PACK__ MrvlIEtypes_Data_t; + +/** MrvlIEtypes_ChanListParamSet_t */ +typedef struct _MrvlIEtypes_MacAddr_t +{ + /** Header */ + MrvlIEtypesHeader_t Header; + /** AP MAC address */ + u8 ApMacAddr[ETH_ALEN]; +} __ATTRIB_PACK__ MrvlIEtypes_MacAddr_t; + +/** Event ID: BSS started */ +#define MICRO_AP_EV_ID_BSS_START 46 + +/** Event ID: BSS idle event */ +#define MICRO_AP_EV_BSS_IDLE 67 + +/** Event ID: BSS active event */ +#define MICRO_AP_EV_BSS_ACTIVE 68 + +/** Event ID: PS_AWAKE */ +#define EVENT_PS_AWAKE 0x0a + +/** Event ID: PS_SLEEP */ +#define EVENT_PS_SLEEP 0x0b + +/** PS_STATE */ +typedef enum _PS_STATE +{ + PS_STATE_AWAKE, + PS_STATE_PRE_SLEEP, + PS_STATE_SLEEP +} PS_STATE; + +/** TLV type: AP Sleep param */ +#define TLV_TYPE_AP_SLEEP_PARAM (PROPRIETARY_TLV_BASE_ID + 106) +/** TLV type: AP Inactivity Sleep param */ +#define TLV_TYPE_AP_INACT_SLEEP_PARAM (PROPRIETARY_TLV_BASE_ID + 107) + +/** MrvlIEtypes_sleep_param_t */ +typedef struct _MrvlIEtypes_sleep_param_t +{ + /** Header */ + MrvlIEtypesHeader_t header; + /** control bitmap */ + u32 ctrl_bitmap; + /** min_sleep */ + u32 min_sleep; + /** max_sleep */ + u32 max_sleep; +} __ATTRIB_PACK__ MrvlIEtypes_sleep_param_t; + +/** MrvlIEtypes_inact_sleep_param_t */ +typedef struct _MrvlIEtypes_inact_sleep_param_t +{ + /** Header */ + MrvlIEtypesHeader_t header; + /** inactivity timeout */ + u32 inactivity_to; + /** min_awake */ + u32 min_awake; + /** max_awake */ + u32 max_awake; +} __ATTRIB_PACK__ MrvlIEtypes_inact_sleep_param_t; + +/** AP_Event */ +typedef struct _AP_Event +{ + /** Event ID */ + u32 EventId; + /* + * Reserved for STA_ASSOCIATED event and contains + * status information for the MIC_COUNTERMEASURES event. + */ + /** Reserved/status */ + u16 status; + /** AP MAC address */ + u8 MacAddr[ETH_ALEN]; +} __ATTRIB_PACK__ AP_Event; +#endif /* _UAP_FW_H */ diff --git a/libertas_uap/uap_headers.h b/libertas_uap/uap_headers.h new file mode 100644 index 0000000..fa09af4 --- /dev/null +++ b/libertas_uap/uap_headers.h @@ -0,0 +1,64 @@ +/** @file uap_headers.h + * + * @brief This file contains all the necessary include file. + * + * Copyright (C) 2008-2009, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available along with the File in the gpl.txt file or by writing to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ +#ifndef _UAP_HEADERS_H +#define _UAP_HEADERS_H + +/* Linux header files */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) +#include +#else +#include +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) +#include +#endif + +/* Net header files */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "uap_drv.h" +#include "uap_fw.h" + +#include +#include +#include +#include +#include "uap_sdio_mmc.h" + +#endif /* _UAP_HEADERS_H */ diff --git a/libertas_uap/uap_main.c b/libertas_uap/uap_main.c new file mode 100644 index 0000000..0cbbe1f --- /dev/null +++ b/libertas_uap/uap_main.c @@ -0,0 +1,1815 @@ +/** @file uap_main.c + * @brief This file contains the major functions in uAP + * driver. It includes init, exit etc.. + * This file also contains the initialization for SW, + * FW and HW + * + * Copyright (C) 2008-2009, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available along with the File in the gpl.txt file or by writing to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ +/** + * @mainpage uAP Linux Driver + * + * @section overview_sec Overview + * + * This is Linux reference driver for Marvell uAP. + * + * @section copyright_sec Copyright + * + * Copyright (C) 2008, Marvell International Ltd. + * + */ + +#include "uap_headers.h" + +/** + * the global variable of a pointer to uap_private + * structure variable + */ +uap_private *uappriv = NULL; +#ifdef DEBUG_LEVEL1 +#define DEFAULT_DEBUG_MASK (DBG_MSG | DBG_FATAL | DBG_ERROR) +u32 drvdbg = DEFAULT_DEBUG_MASK; +#endif +/** Helper name */ +char *helper_name = NULL; +/** Firmware name */ +char *fw_name = NULL; + +/** Semaphore for add/remove card */ +SEMAPHORE AddRemoveCardSem; + +/******************************************************** + Local Functions +********************************************************/ +/** + * @brief This function send sleep confirm command to firmware + * + * @param priv A pointer to uap_private structure + * @return UAP_STATUS_SUCCESS for success otherwise UAP_STATUS_FAILURE + */ +static int +uap_dnld_sleep_confirm_cmd(uap_private * priv) +{ + uap_adapter *Adapter = priv->adapter; + int ret = UAP_STATUS_SUCCESS; + ENTER(); + PRINTM(CMND, "Sleep confirm\n"); + Adapter->cmd_pending = TRUE; + Adapter->cmd_wait_option = HostCmd_OPTION_WAITFORRSP_SLEEPCONFIRM; + ret = + sbi_host_to_card(priv, (u8 *) & Adapter->PSConfirmSleep, + sizeof(PS_CMD_ConfirmSleep)); + if (ret != UAP_STATUS_SUCCESS) { + Adapter->ps_state = PS_STATE_AWAKE; + Adapter->cmd_pending = FALSE; + Adapter->cmd_wait_option = FALSE; + } + LEAVE(); + return ret; +} + +/** + * @brief This function process sleep confirm resp from firmware + * + * @param priv A pointer to uap_private structure + * @param resp A pointer to resp buf + * @param resp_len resp buf len + * @return UAP_STATUS_SUCCESS for success otherwise UAP_STATUS_FAILURE + */ +int +uap_process_sleep_confirm_resp(uap_private * priv, u8 * resp, int resp_len) +{ + int ret = UAP_STATUS_SUCCESS; + HostCmd_DS_COMMAND *cmd; + uap_adapter *Adapter = priv->adapter; + ENTER(); + PRINTM(CMND, "Sleep confirm resp\n"); + if (!resp_len) { + PRINTM(ERROR, "Cmd Size is 0\n"); + ret = -EFAULT; + goto done; + } + cmd = (HostCmd_DS_COMMAND *) resp; + cmd->Result = uap_le16_to_cpu(cmd->Result); + if (cmd->Result != UAP_STATUS_SUCCESS) { + PRINTM(ERROR, "HOST_CMD_APCMD_PS_SLEEP_CONFIRM fail=%x\n", cmd->Result); + ret = -EFAULT; + } + done: + if (ret == UAP_STATUS_SUCCESS) + Adapter->ps_state = PS_STATE_SLEEP; + else + Adapter->ps_state = PS_STATE_AWAKE; + LEAVE(); + return ret; +} + +/** + * @brief This function checks condition and prepares to + * send sleep confirm command to firmware if OK. + * + * @param priv A pointer to uap_private structure + * @return n/a + */ +static void +uap_ps_cond_check(uap_private * priv) +{ + uap_adapter *Adapter = priv->adapter; + + ENTER(); + if (!priv->uap_dev.cmd_sent && + !Adapter->cmd_pending && !Adapter->IntCounter) { + uap_dnld_sleep_confirm_cmd(priv); + } else { + PRINTM(INFO, "Delay Sleep Confirm (%s%s%s)\n", + (priv->uap_dev.cmd_sent) ? "D" : "", + (Adapter->cmd_pending) ? "C" : "", + (Adapter->IntCounter) ? "I" : ""); + } + LEAVE(); +} + +/** + * @brief This function add cmd to cmdQ and waiting for response + * + * @param priv A pointer to uap_private structure + * @param skb A pointer to the skb for process + * @param wait_option Wait option + * @return UAP_STATUS_SUCCESS for success otherwise UAP_STATUS_FAILURE + */ +static int +uap_process_cmd(uap_private * priv, struct sk_buff *skb, u8 wait_option) +{ + uap_adapter *Adapter = priv->adapter; + int ret = UAP_STATUS_SUCCESS; + HostCmd_DS_COMMAND *cmd; + u8 *headptr; + ENTER(); + if (Adapter->HardwareStatus != HWReady) { + PRINTM(ERROR, "Hw not ready, uap_process_cmd\n"); + kfree(skb); + LEAVE(); + return -EFAULT; + } + skb->cb[0] = wait_option; + headptr = skb->data; + *(u16 *) & headptr[0] = uap_cpu_to_le16(skb->len); + *(u16 *) & headptr[2] = uap_cpu_to_le16(MV_TYPE_CMD); + cmd = (HostCmd_DS_COMMAND *) (skb->data + INTF_HEADER_LEN); + Adapter->SeqNum++; + cmd->SeqNum = uap_cpu_to_le16(Adapter->SeqNum); + PRINTM(CMND, "process_cmd: %x\n", cmd->Command); + DBG_HEXDUMP(CMD_D, "process_cmd", (u8 *) cmd, cmd->Size); + if (!wait_option) { + skb_queue_tail(&priv->adapter->cmd_queue, skb); + wake_up_interruptible(&priv->MainThread.waitQ); + LEAVE(); + return ret; + } + if (OS_ACQ_SEMAPHORE_BLOCK(&Adapter->CmdSem)) { + PRINTM(ERROR, "Acquire semaphore error, uap_prepare_cmd\n"); + kfree(skb); + LEAVE(); + return -EBUSY; + } + skb_queue_tail(&priv->adapter->cmd_queue, skb); + Adapter->CmdWaitQWoken = FALSE; + wake_up_interruptible(&priv->MainThread.waitQ); + /* Sleep until response is generated by FW */ + if (wait_option == HostCmd_OPTION_WAITFORRSP_TIMEOUT) { + if (!os_wait_interruptible_timeout + (Adapter->cmdwait_q, Adapter->CmdWaitQWoken, MRVDRV_TIMER_20S)) { + PRINTM(ERROR, "Cmd timeout\n"); + Adapter->cmd_pending = FALSE; + ret = -EFAULT; + } + } else + wait_event_interruptible(Adapter->cmdwait_q, Adapter->CmdWaitQWoken); + OS_REL_SEMAPHORE(&Adapter->CmdSem); + LEAVE(); + return ret; +} + +/** + * @brief Inspect the response buffer for pointers to expected TLVs + * + * + * @param pTlv Pointer to the start of the TLV buffer to parse + * @param tlvBufSize Size of the TLV buffer + * @param reqTlvType request tlv's tlvtype + * @param ppTlv Output parameter: Pointer to the request TLV if found + * + * @return void + */ +static void +uap_get_tlv_ptrs(MrvlIEtypes_Data_t * pTlv, int tlvBufSize, + u16 reqTlvType, MrvlIEtypes_Data_t ** ppTlv) +{ + MrvlIEtypes_Data_t *pCurrentTlv; + int tlvBufLeft; + u16 tlvType; + u16 tlvLen; + + ENTER(); + pCurrentTlv = pTlv; + tlvBufLeft = tlvBufSize; + *ppTlv = NULL; + PRINTM(INFO, "uap_get_tlv: tlvBufSize = %d, reqTlvType=%x\n", tlvBufSize, + reqTlvType); + while (tlvBufLeft >= sizeof(MrvlIEtypesHeader_t)) { + tlvType = uap_le16_to_cpu(pCurrentTlv->Header.Type); + tlvLen = uap_le16_to_cpu(pCurrentTlv->Header.Len); + if (reqTlvType == tlvType) + *ppTlv = (MrvlIEtypes_Data_t *) pCurrentTlv; + if (*ppTlv) { + HEXDUMP("TLV Buf", (u8 *) * ppTlv, tlvLen); + break; + } + tlvBufLeft -= (sizeof(pTlv->Header) + tlvLen); + pCurrentTlv = (MrvlIEtypes_Data_t *) (pCurrentTlv->Data + tlvLen); + } /* while */ + LEAVE(); +} + +/** + * @brief This function get mac + * + * @param priv A pointer to uap_private structure + * @return UAP_STATUS_SUCCESS on success, otherwise failure code + */ +static int +uap_get_mac_address(uap_private * priv) +{ + int ret = UAP_STATUS_SUCCESS; + u32 CmdSize; + HostCmd_DS_COMMAND *cmd; + uap_adapter *Adapter = priv->adapter; + struct sk_buff *skb; + MrvlIEtypes_MacAddr_t *pMacAddrTlv; + MrvlIEtypes_Data_t *pTlv; + u16 tlvBufSize; + ENTER(); + skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER); + if (!skb) { + PRINTM(ERROR, "No free skb\n"); + ret = -ENOMEM; + goto done; + } + CmdSize = + S_DS_GEN + sizeof(HostCmd_SYS_CONFIG) + sizeof(MrvlIEtypes_MacAddr_t); + cmd = (HostCmd_DS_COMMAND *) (skb->data + INTF_HEADER_LEN); + cmd->Command = uap_cpu_to_le16(HOST_CMD_APCMD_SYS_CONFIGURE); + cmd->Size = uap_cpu_to_le16(CmdSize); + cmd->params.sys_config.Action = uap_cpu_to_le16(ACTION_GET); + pMacAddrTlv = + (MrvlIEtypes_MacAddr_t *) (skb->data + INTF_HEADER_LEN + S_DS_GEN + + sizeof(HostCmd_SYS_CONFIG)); + pMacAddrTlv->Header.Type = uap_cpu_to_le16(MRVL_AP_MAC_ADDRESS_TLV_ID); + pMacAddrTlv->Header.Len = uap_cpu_to_le16(ETH_ALEN); + skb_put(skb, CmdSize + INTF_HEADER_LEN); + if (UAP_STATUS_SUCCESS != + uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP_TIMEOUT)) { + PRINTM(ERROR, "Fail to process cmd SYS_CONFIGURE Query\n"); + ret = -EFAULT; + goto done; + } + if (!Adapter->CmdSize) { + PRINTM(ERROR, "Cmd Size is 0\n"); + ret = -EFAULT; + goto done; + } + cmd = (HostCmd_DS_COMMAND *) Adapter->CmdBuf; + cmd->Result = uap_le16_to_cpu(cmd->Result); + if (cmd->Result != UAP_STATUS_SUCCESS) { + PRINTM(ERROR, "uap_get_mac_address fail=%x\n", cmd->Result); + ret = -EFAULT; + goto done; + } + pTlv = + (MrvlIEtypes_Data_t *) (Adapter->CmdBuf + S_DS_GEN + + sizeof(HostCmd_SYS_CONFIG)); + tlvBufSize = Adapter->CmdSize - S_DS_GEN - sizeof(HostCmd_SYS_CONFIG); + uap_get_tlv_ptrs(pTlv, tlvBufSize, MRVL_AP_MAC_ADDRESS_TLV_ID, + (MrvlIEtypes_Data_t **) & pMacAddrTlv); + if (pMacAddrTlv) { + memcpy(priv->uap_dev.netdev->dev_addr, pMacAddrTlv->ApMacAddr, + ETH_ALEN); + HEXDUMP("Original MAC addr", priv->uap_dev.netdev->dev_addr, ETH_ALEN); + } + done: + LEAVE(); + return ret; +} + +/** + * @brief This function checks the conditions and sends packet to device + * + * @param priv A pointer to uap_private structure + * @param skb A pointer to the skb for process + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE + */ +static int +uap_process_tx(uap_private * priv, struct sk_buff *skb) +{ + uap_adapter *Adapter = priv->adapter; + int ret = UAP_STATUS_SUCCESS; + TxPD *pLocalTxPD; + u8 *headptr; + struct sk_buff *newskb; + int newheadlen; + ENTER(); + ASSERT(skb); + if (!skb) { + LEAVE(); + return UAP_STATUS_FAILURE; + } + if (skb_headroom(skb) < (sizeof(TxPD) + INTF_HEADER_LEN + HEADER_ALIGNMENT)) { + newheadlen = sizeof(TxPD) + INTF_HEADER_LEN + HEADER_ALIGNMENT; + PRINTM(WARN, "Tx: Insufficient skb headroom %d\n", skb_headroom(skb)); + /* Insufficient skb headroom - allocate a new skb */ + newskb = skb_realloc_headroom(skb, newheadlen); + if (unlikely(newskb == NULL)) { + PRINTM(ERROR, "Tx: Cannot allocate skb\n"); + ret = UAP_STATUS_FAILURE; + goto done; + } + kfree_skb(skb); + skb = newskb; + PRINTM(INFO, "new skb headroom %d\n", skb_headroom(skb)); + } + /* headptr should be aligned */ + headptr = skb->data - sizeof(TxPD) - INTF_HEADER_LEN; + headptr = (u8 *) ((u32) headptr & ~((u32) (HEADER_ALIGNMENT - 1))); + + pLocalTxPD = (TxPD *) (headptr + INTF_HEADER_LEN); + memset(pLocalTxPD, 0, sizeof(TxPD)); + pLocalTxPD->BssType = PKT_TYPE_MICROAP; + pLocalTxPD->TxPktLength = skb->len; + /* offset of actual data */ + pLocalTxPD->TxPktOffset = (long) skb->data - (long) pLocalTxPD; + endian_convert_TxPD(pLocalTxPD); + *(u16 *) & headptr[0] = + uap_cpu_to_le16(skb->len + ((long) skb->data - (long) headptr)); + *(u16 *) & headptr[2] = uap_cpu_to_le16(MV_TYPE_DAT); + ret = + sbi_host_to_card(priv, headptr, + skb->len + ((long) skb->data - (long) headptr)); + if (ret) { + PRINTM(ERROR, "uap_process_tx Error: sbi_host_to_card failed: 0x%X\n", + ret); + Adapter->dbg.num_tx_host_to_card_failure++; + goto done; + } + PRINTM(DATA, "Data => FW\n"); + DBG_HEXDUMP(DAT_D, "Tx", headptr, + MIN(skb->len + sizeof(TxPD), DATA_DUMP_LEN)); + done: + /* Freed skb */ + kfree_skb(skb); + LEAVE(); + return ret; +} + +/** + * @brief This function initializes the adapter structure + * and set default value to the member of adapter. + * + * @param priv A pointer to uap_private structure + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE + */ +static int +uap_init_sw(uap_private * priv) +{ + uap_adapter *Adapter = priv->adapter; + + ENTER(); + + if (!(Adapter->CmdBuf = kmalloc(MRVDRV_SIZE_OF_CMD_BUFFER, GFP_KERNEL))) { + PRINTM(INFO, "Failed to allocate command buffer!\n"); + LEAVE(); + return UAP_STATUS_FAILURE; + } + + Adapter->cmd_pending = FALSE; + Adapter->CmdWaitQWoken = FALSE; + Adapter->ps_state = PS_STATE_AWAKE; + Adapter->WakeupTries = 0; + + memset(&Adapter->PSConfirmSleep, 0, sizeof(PS_CMD_ConfirmSleep)); + /** SDIO header */ + Adapter->PSConfirmSleep.SDLen = + uap_cpu_to_le16(sizeof(PS_CMD_ConfirmSleep)); + Adapter->PSConfirmSleep.SDType = uap_cpu_to_le16(MV_TYPE_CMD); + Adapter->PSConfirmSleep.SeqNum = 0; + Adapter->PSConfirmSleep.Command = uap_cpu_to_le16(HOST_CMD_SLEEP_CONFIRM); + Adapter->PSConfirmSleep.Size = uap_cpu_to_le16(sizeof(HostCmd_DS_GEN)); + Adapter->PSConfirmSleep.Result = 0; + + init_waitqueue_head(&Adapter->cmdwait_q); + OS_INIT_SEMAPHORE(&Adapter->CmdSem); + + skb_queue_head_init(&Adapter->tx_queue); + skb_queue_head_init(&Adapter->cmd_queue); + + /* Status variable */ + Adapter->HardwareStatus = HWInitializing; + + /* PnP support */ + Adapter->SurpriseRemoved = FALSE; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) + Adapter->nl_sk = netlink_kernel_create(NETLINK_MARVELL, + NL_MULTICAST_GROUP, NULL, + THIS_MODULE); +#else +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) + Adapter->nl_sk = netlink_kernel_create(NETLINK_MARVELL, + NL_MULTICAST_GROUP, NULL, NULL, + THIS_MODULE); +#else + Adapter->nl_sk = netlink_kernel_create(&init_net, NETLINK_MARVELL, + NL_MULTICAST_GROUP, NULL, NULL, + THIS_MODULE); +#endif +#endif + if (!Adapter->nl_sk) { + PRINTM(ERROR, + "Could not initialize netlink event passing mechanism!\n"); + } + LEAVE(); + return UAP_STATUS_SUCCESS; +} + +/** + * @brief This function sends FUNC_INIT command to firmware + * + * @param priv A pointer to uap_private structure + * @return UAP_STATUS_SUCCESS on success, otherwise failure code + */ +static int +uap_func_init(uap_private * priv) +{ + int ret = UAP_STATUS_SUCCESS; + u32 CmdSize; + HostCmd_DS_GEN *cmd; + uap_adapter *Adapter = priv->adapter; + struct sk_buff *skb; + ENTER(); + if (Adapter->HardwareStatus != HWReady) { + PRINTM(ERROR, "uap_func_init:Hardware is not ready!\n"); + ret = -EFAULT; + goto done; + } + skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER); + if (!skb) { + PRINTM(ERROR, "No free skb\n"); + ret = -ENOMEM; + goto done; + } + CmdSize = sizeof(HostCmd_DS_GEN); + cmd = (HostCmd_DS_GEN *) (skb->data + INTF_HEADER_LEN); + cmd->Command = uap_cpu_to_le16(HostCmd_CMD_FUNC_INIT); + cmd->Size = uap_cpu_to_le16(CmdSize); + skb_put(skb, CmdSize + INTF_HEADER_LEN); + PRINTM(CMND, "HostCmd_CMD_FUNC_INIT\n"); + if (UAP_STATUS_SUCCESS != + uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP_TIMEOUT)) { + PRINTM(ERROR, "Fail to process cmd HostCmd_CMD_FUNC_INIT\n"); + ret = -EFAULT; + goto done; + } + done: + LEAVE(); + return ret; +} + +/** + * @brief This function sends FUNC_SHUTDOWN command to firmware + * + * @param priv A pointer to uap_private structure + * @return UAP_STATUS_SUCCESS on success, otherwise failure code + */ +static int __exit +uap_func_shutdown(uap_private * priv) +{ + int ret = UAP_STATUS_SUCCESS; + u32 CmdSize; + HostCmd_DS_GEN *cmd; + uap_adapter *Adapter = priv->adapter; + struct sk_buff *skb; + ENTER(); + if (Adapter->HardwareStatus != HWReady) { + PRINTM(ERROR, "uap_func_shutdown:Hardware is not ready!\n"); + ret = -EFAULT; + goto done; + } + skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER); + if (!skb) { + PRINTM(ERROR, "No free skb\n"); + ret = -ENOMEM; + goto done; + } + CmdSize = sizeof(HostCmd_DS_GEN); + cmd = (HostCmd_DS_GEN *) (skb->data + INTF_HEADER_LEN); + cmd->Command = uap_cpu_to_le16(HostCmd_CMD_FUNC_SHUTDOWN); + cmd->Size = uap_cpu_to_le16(CmdSize); + skb_put(skb, CmdSize + INTF_HEADER_LEN); + PRINTM(CMND, "HostCmd_CMD_FUNC_SHUTDOWN\n"); + if (UAP_STATUS_SUCCESS != + uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP_TIMEOUT)) { + PRINTM(ERROR, "Fail to process cmd HostCmd_CMD_FUNC_SHUTDOWN\n"); + ret = -EFAULT; + goto done; + } + done: + LEAVE(); + return ret; +} + +/** + * @brief This function initializes firmware + * + * @param priv A pointer to uap_private structure + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE + */ +static int +uap_init_fw(uap_private * priv) +{ + int ret = UAP_STATUS_SUCCESS; + ENTER(); + sbi_disable_host_int(priv); + /* Check if firmware is already running */ + if (sbi_check_fw_status(priv, 1) == UAP_STATUS_SUCCESS) { + PRINTM(MSG, "UAP FW already running! Skip FW download\n"); + } else { + if ((ret = request_firmware(&priv->fw_helper, helper_name, + priv->hotplug_device)) < 0) { + PRINTM(FATAL, + "request_firmware() failed (helper), error code = %#x\n", + ret); + goto done; + } + + /* Download the helper */ + ret = sbi_prog_helper(priv); + + if (ret) { + PRINTM(FATAL, + "Bootloader in invalid state! Helper download failed!\n"); + ret = UAP_STATUS_FAILURE; + goto done; + } + if ((ret = request_firmware(&priv->firmware, fw_name, + priv->hotplug_device)) < 0) { + PRINTM(FATAL, "request_firmware() failed, error code = %#x\n", ret); + goto done; + } + + /* Download the main firmware via the helper firmware */ + if (sbi_prog_fw_w_helper(priv)) { + PRINTM(FATAL, "UAP FW download failed!\n"); + ret = UAP_STATUS_FAILURE; + goto done; + } + /* Check if the firmware is downloaded successfully or not */ + if (sbi_check_fw_status(priv, MAX_FIRMWARE_POLL_TRIES) == + UAP_STATUS_FAILURE) { + PRINTM(FATAL, "FW failed to be active in time!\n"); + ret = UAP_STATUS_FAILURE; + goto done; + } + PRINTM(MSG, "UAP FW is active\n"); + } + sbi_enable_host_int(priv); + priv->adapter->HardwareStatus = HWReady; + if (uap_func_init(priv) != UAP_STATUS_SUCCESS) { + ret = UAP_STATUS_FAILURE; + goto done; + } + done: + if (priv->fw_helper) + release_firmware(priv->fw_helper); + if (priv->firmware) + release_firmware(priv->firmware); + LEAVE(); + return ret; + +} + +/** + * @brief This function frees the structure of adapter + * + * @param priv A pointer to uap_private structure + * @return n/a + */ +static void +uap_free_adapter(uap_private * priv) +{ + uap_adapter *Adapter = priv->adapter; + + ENTER(); + + if (Adapter) { + if ((Adapter->nl_sk) && ((Adapter->nl_sk)->sk_socket)) { + sock_release((Adapter->nl_sk)->sk_socket); + Adapter->nl_sk = NULL; + } + if (Adapter->CmdBuf) + kfree(Adapter->CmdBuf); + skb_queue_purge(&priv->adapter->tx_queue); + skb_queue_purge(&priv->adapter->cmd_queue); + /* Free the adapter object itself */ + kfree(Adapter); + priv->adapter = NULL; + } + + LEAVE(); +} + +/** + * @brief This function handles the major job in uap driver. + * it handles the event generated by firmware, rx data received + * from firmware and tx data sent from kernel. + * + * @param data A pointer to uap_thread structure + * @return BT_STATUS_SUCCESS + */ +static int +uap_service_main_thread(void *data) +{ + uap_thread *thread = data; + uap_private *priv = thread->priv; + uap_adapter *Adapter = priv->adapter; + wait_queue_t wait; + u8 ireg = 0; + struct sk_buff *skb; + ENTER(); + uap_activate_thread(thread); + init_waitqueue_entry(&wait, current); + current->flags |= PF_NOFREEZE; + + for (;;) { + add_wait_queue(&thread->waitQ, &wait); + OS_SET_THREAD_STATE(TASK_INTERRUPTIBLE); + if ((Adapter->WakeupTries) || + (!Adapter->IntCounter && Adapter->ps_state == PS_STATE_PRE_SLEEP) || + (!priv->adapter->IntCounter + && (priv->uap_dev.data_sent || + skb_queue_empty(&priv->adapter->tx_queue)) + && (priv->uap_dev.cmd_sent || Adapter->cmd_pending || + skb_queue_empty(&priv->adapter->cmd_queue)) + )) { + PRINTM(INFO, "Main: Thread sleeping...\n"); + schedule(); + } + OS_SET_THREAD_STATE(TASK_RUNNING); + remove_wait_queue(&thread->waitQ, &wait); + if (kthread_should_stop() || Adapter->SurpriseRemoved) { + PRINTM(INFO, "main-thread: break from main thread: " + "SurpriseRemoved=0x%x\n", Adapter->SurpriseRemoved); + /* Cancel pending command */ + if (Adapter->cmd_pending == TRUE) { + /* Wake up cmd Q */ + Adapter->CmdWaitQWoken = TRUE; + wake_up_interruptible(&Adapter->cmdwait_q); + } + break; + } + + PRINTM(INFO, "Main: Thread waking up...\n"); + if (priv->adapter->IntCounter) { + OS_INT_DISABLE; + Adapter->IntCounter = 0; + OS_INT_RESTORE; + sbi_get_int_status(priv, &ireg); + } else if ((priv->adapter->ps_state == PS_STATE_SLEEP) && + (!skb_queue_empty(&priv->adapter->cmd_queue) || + !skb_queue_empty(&priv->adapter->tx_queue))) { + priv->adapter->WakeupTries++; + PRINTM(CMND, "%lu : Wakeup device...\n", os_time_get()); + sbi_wakeup_firmware(priv); + continue; + } + if (Adapter->ps_state == PS_STATE_PRE_SLEEP) + uap_ps_cond_check(priv); + + /* The PS state is changed during processing of Sleep Request event + above */ + if ((Adapter->ps_state == PS_STATE_SLEEP) || + (Adapter->ps_state == PS_STATE_PRE_SLEEP)) + continue; + /* Execute the next command */ + if (!priv->uap_dev.cmd_sent && !Adapter->cmd_pending && + (Adapter->HardwareStatus == HWReady)) { + if (!skb_queue_empty(&priv->adapter->cmd_queue)) { + skb = skb_dequeue(&priv->adapter->cmd_queue); + if (skb) { + Adapter->CmdSize = 0; + Adapter->cmd_pending = TRUE; + Adapter->cmd_wait_option = skb->cb[0]; + if (sbi_host_to_card(priv, skb->data, skb->len)) { + PRINTM(ERROR, "Cmd:sbi_host_to_card failed!\n"); + Adapter->cmd_pending = FALSE; + Adapter->dbg.num_cmd_host_to_card_failure++; + /* Wake up cmd Q */ + Adapter->CmdWaitQWoken = TRUE; + wake_up_interruptible(&Adapter->cmdwait_q); + } else { + if (Adapter->cmd_wait_option == + HostCmd_OPTION_WAITFORSEND) { + /* Wake up cmd Q */ + Adapter->CmdWaitQWoken = TRUE; + wake_up_interruptible(&Adapter->cmdwait_q); + Adapter->cmd_wait_option = FALSE; + } + } + kfree_skb(skb); + } + } + } + if (!priv->uap_dev.data_sent && (Adapter->HardwareStatus == HWReady)) { + if (!skb_queue_empty(&priv->adapter->tx_queue)) { + skb = skb_dequeue(&priv->adapter->tx_queue); + if (skb) { + if (uap_process_tx(priv, skb)) { + priv->stats.tx_dropped++; + priv->stats.tx_errors++; + os_start_queue(priv); + } else { + priv->stats.tx_packets++; + priv->stats.tx_bytes += skb->len; + } + + } + } + } + } + uap_deactivate_thread(thread); + LEAVE(); + return UAP_STATUS_SUCCESS; +} + +/** + * @brief uap hostcmd ioctl handler + * + * @param dev A pointer to net_device structure + * @param req A pointer to ifreq structure + * @return UAP_STATUS_SUCCESS --success, otherwise fail + */ +/********* format of ifr_data *************/ +/* buf_len + Hostcmd_body */ +/* buf_len: 4 bytes */ +/* the length of the buf which */ +/* can be used to return data */ +/* to application */ +/* Hostcmd_body */ +/*******************************************/ +static int +uap_hostcmd_ioctl(struct net_device *dev, struct ifreq *req) +{ + u32 buf_len; + HostCmd_HEADER head; + uap_private *priv = (uap_private *) netdev_priv(dev); + uap_adapter *Adapter = priv->adapter; + int ret = UAP_STATUS_SUCCESS; + struct sk_buff *skb; + + ENTER(); + + /* Sanity check */ + if (req->ifr_data == NULL) { + PRINTM(ERROR, "uap_hostcmd_ioctl() corrupt data\n"); + LEAVE(); + return -EFAULT; + } + if (copy_from_user(&buf_len, req->ifr_data, sizeof(buf_len))) { + PRINTM(ERROR, "Copy from user failed\n"); + LEAVE(); + return -EFAULT; + } + memset(&head, 0, sizeof(HostCmd_HEADER)); + /* Get the command size from user space */ + if (copy_from_user + (&head, req->ifr_data + sizeof(buf_len), sizeof(HostCmd_HEADER))) { + PRINTM(ERROR, "Copy from user failed\n"); + LEAVE(); + return -EFAULT; + } + head.Size = uap_le16_to_cpu(head.Size); + if (head.Size > MRVDRV_SIZE_OF_CMD_BUFFER) { + PRINTM(ERROR, "CmdSize too big=%d\n", head.Size); + LEAVE(); + return -EFAULT; + } + PRINTM(CMND, "ioctl: hostcmd=%x, size=%d,buf_len=%d\n", head.Command, + head.Size, buf_len); + skb = dev_alloc_skb(head.Size + INTF_HEADER_LEN); + if (!skb) { + PRINTM(ERROR, "No free skb\n"); + LEAVE(); + return -ENOMEM; + } + + /* Get the command from user space */ + if (copy_from_user + (skb->data + INTF_HEADER_LEN, req->ifr_data + sizeof(buf_len), + head.Size)) { + PRINTM(ERROR, "Copy from user failed\n"); + LEAVE(); + return -EFAULT; + } + skb_put(skb, head.Size + INTF_HEADER_LEN); + if (UAP_STATUS_SUCCESS != + uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP)) { + PRINTM(ERROR, "Fail to process cmd\n"); + LEAVE(); + return -EFAULT; + } + if (!Adapter->CmdSize) { + PRINTM(ERROR, "Cmd Size is 0\n"); + LEAVE(); + return -EFAULT; + } + if (Adapter->CmdSize > buf_len) { + PRINTM(ERROR, "buf_len is too small\n"); + LEAVE(); + return -EFAULT; + } + /* Copy to user */ + if (copy_to_user + (req->ifr_data + sizeof(buf_len), Adapter->CmdBuf, Adapter->CmdSize)) { + PRINTM(ERROR, "Copy to user failed!\n"); + LEAVE(); + return -EFAULT; + } + LEAVE(); + return ret; +} + +/** + * @brief uap power mode ioctl handler + * + * @param dev A pointer to net_device structure + * @param req A pointer to ifreq structure + * @return UAP_STATUS_SUCCESS --success, otherwise fail + */ +static int +uap_power_mode_ioctl(struct net_device *dev, struct ifreq *req) +{ + ps_mgmt pm_cfg; + int ret = UAP_STATUS_SUCCESS; + uap_private *priv = (uap_private *) netdev_priv(dev); + uap_adapter *Adapter = priv->adapter; + struct sk_buff *skb = NULL; + HostCmd_DS_COMMAND *cmd; + u32 CmdSize; + u8 *tlv = NULL; + MrvlIEtypes_sleep_param_t *sleep_tlv = NULL; + MrvlIEtypes_inact_sleep_param_t *inact_tlv = NULL; + u16 tlv_buf_left = 0; + MrvlIEtypesHeader_t *tlvbuf = NULL; + u16 tlv_type = 0; + u16 tlv_len = 0; + + ENTER(); + + /* Sanity check */ + if (req->ifr_data == NULL) { + PRINTM(ERROR, "uap_power_mode_ioctl() corrupt data\n"); + LEAVE(); + return -EFAULT; + } + + memset(&pm_cfg, 0, sizeof(ps_mgmt)); + if (copy_from_user(&pm_cfg, req->ifr_data, sizeof(ps_mgmt))) { + PRINTM(ERROR, "Copy from user failed\n"); + LEAVE(); + return -EFAULT; + } + PRINTM(CMND, + "ioctl power: flag=0x%x ps_mode=%d ctrl_bitmap=%d min_sleep=%d max_sleep=%d " + "inact_to=%d min_awake=%d max_awake=%d\n", pm_cfg.flags, + (int) pm_cfg.ps_mode, (int) pm_cfg.sleep_param.ctrl_bitmap, + (int) pm_cfg.sleep_param.min_sleep, + (int) pm_cfg.sleep_param.max_sleep, + (int) pm_cfg.inact_param.inactivity_to, + (int) pm_cfg.inact_param.min_awake, + (int) pm_cfg.inact_param.max_awake); + + if (pm_cfg. + flags & ~(PS_FLAG_PS_MODE | PS_FLAG_SLEEP_PARAM | + PS_FLAG_INACT_SLEEP_PARAM)) { + PRINTM(ERROR, "Invalid parameter: flags = 0x%x\n", pm_cfg.flags); + ret = -EINVAL; + goto done; + } + if (pm_cfg.ps_mode > PS_MODE_INACTIVITY) { + PRINTM(ERROR, "Invalid parameter: ps_mode = %d\n", (int) pm_cfg.flags); + ret = -EINVAL; + goto done; + } + + skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER); + if (!skb) { + PRINTM(INFO, "No free skb\n"); + ret = -ENOMEM; + goto done; + } + + CmdSize = S_DS_GEN + sizeof(HostCmd_DS_POWER_MGMT_EXT); + + cmd = (HostCmd_DS_COMMAND *) (skb->data + INTF_HEADER_LEN); + cmd->Command = uap_cpu_to_le16(HOST_CMD_POWER_MGMT_EXT); + if (!pm_cfg.flags) { + cmd->params.pm_cfg.action = uap_cpu_to_le16(ACTION_GET); + } else { + cmd->params.pm_cfg.action = uap_cpu_to_le16(ACTION_SET); + cmd->params.pm_cfg.power_mode = uap_cpu_to_le16(pm_cfg.ps_mode); + tlv = (u8 *) & cmd->params.pm_cfg + sizeof(HostCmd_DS_POWER_MGMT_EXT); + + if ((pm_cfg.ps_mode) && (pm_cfg.flags & PS_FLAG_SLEEP_PARAM)) { + sleep_tlv = (MrvlIEtypes_sleep_param_t *) tlv; + sleep_tlv->header.Type = uap_cpu_to_le16(TLV_TYPE_AP_SLEEP_PARAM); + sleep_tlv->header.Len = + uap_cpu_to_le16(sizeof(MrvlIEtypes_sleep_param_t) - + sizeof(MrvlIEtypesHeader_t)); + sleep_tlv->ctrl_bitmap = + uap_cpu_to_le32(pm_cfg.sleep_param.ctrl_bitmap); + sleep_tlv->min_sleep = + uap_cpu_to_le32(pm_cfg.sleep_param.min_sleep); + sleep_tlv->max_sleep = + uap_cpu_to_le32(pm_cfg.sleep_param.max_sleep); + CmdSize += sizeof(MrvlIEtypes_sleep_param_t); + tlv += sizeof(MrvlIEtypes_sleep_param_t); + } + if ((pm_cfg.ps_mode == PS_MODE_INACTIVITY) && + (pm_cfg.flags & PS_FLAG_INACT_SLEEP_PARAM)) { + inact_tlv = (MrvlIEtypes_inact_sleep_param_t *) tlv; + inact_tlv->header.Type = + uap_cpu_to_le16(TLV_TYPE_AP_INACT_SLEEP_PARAM); + inact_tlv->header.Len = + uap_cpu_to_le16(sizeof(MrvlIEtypes_inact_sleep_param_t) - + sizeof(MrvlIEtypesHeader_t)); + inact_tlv->inactivity_to = + uap_cpu_to_le32(pm_cfg.inact_param.inactivity_to); + inact_tlv->min_awake = + uap_cpu_to_le32(pm_cfg.inact_param.min_awake); + inact_tlv->max_awake = + uap_cpu_to_le32(pm_cfg.inact_param.max_awake); + CmdSize += sizeof(MrvlIEtypes_inact_sleep_param_t); + tlv += sizeof(MrvlIEtypes_inact_sleep_param_t); + } + } + cmd->Size = uap_cpu_to_le16(CmdSize); + skb_put(skb, CmdSize + INTF_HEADER_LEN); + if (UAP_STATUS_SUCCESS != + uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP)) { + PRINTM(ERROR, "Fail to process cmd POWER_MODE\n"); + ret = -EFAULT; + goto done; + } + if (!Adapter->CmdSize) { + PRINTM(ERROR, "Cmd Size is 0\n"); + ret = -EFAULT; + goto done; + } + cmd = (HostCmd_DS_COMMAND *) Adapter->CmdBuf; + cmd->Result = uap_le16_to_cpu(cmd->Result); + if (cmd->Result != UAP_STATUS_SUCCESS) { + PRINTM(ERROR, "HOST_CMD_APCMD_POWER_MODE fail=%x\n", cmd->Result); + ret = -EFAULT; + goto done; + } + if (pm_cfg.flags) { + Adapter->psmode = uap_le16_to_cpu(cmd->params.pm_cfg.power_mode); + } else { + pm_cfg.flags = PS_FLAG_PS_MODE; + pm_cfg.ps_mode = uap_le16_to_cpu(cmd->params.pm_cfg.power_mode); + tlv_buf_left = + cmd->Size - (sizeof(HostCmd_DS_POWER_MGMT_EXT) + S_DS_GEN); + tlvbuf = + (MrvlIEtypesHeader_t *) ((u8 *) & cmd->params.pm_cfg + + sizeof(HostCmd_DS_POWER_MGMT_EXT)); + while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) { + tlv_type = uap_le16_to_cpu(tlvbuf->Type); + tlv_len = uap_le16_to_cpu(tlvbuf->Len); + switch (tlv_type) { + case TLV_TYPE_AP_SLEEP_PARAM: + sleep_tlv = (MrvlIEtypes_sleep_param_t *) tlvbuf; + pm_cfg.flags |= PS_FLAG_SLEEP_PARAM; + pm_cfg.sleep_param.ctrl_bitmap = + uap_le32_to_cpu(sleep_tlv->ctrl_bitmap); + pm_cfg.sleep_param.min_sleep = + uap_le32_to_cpu(sleep_tlv->min_sleep); + pm_cfg.sleep_param.max_sleep = + uap_le32_to_cpu(sleep_tlv->max_sleep); + break; + case TLV_TYPE_AP_INACT_SLEEP_PARAM: + inact_tlv = (MrvlIEtypes_inact_sleep_param_t *) tlvbuf; + pm_cfg.flags |= PS_FLAG_INACT_SLEEP_PARAM; + pm_cfg.inact_param.inactivity_to = + uap_le32_to_cpu(inact_tlv->inactivity_to); + pm_cfg.inact_param.min_awake = + uap_le32_to_cpu(inact_tlv->min_awake); + pm_cfg.inact_param.max_awake = + uap_le32_to_cpu(inact_tlv->max_awake); + break; + } + tlv_buf_left -= tlv_len + sizeof(MrvlIEtypesHeader_t); + tlvbuf = + (MrvlIEtypesHeader_t *) ((u8 *) tlvbuf + tlv_len + + sizeof(MrvlIEtypesHeader_t)); + } + /* Copy to user */ + if (copy_to_user(req->ifr_data, &pm_cfg, sizeof(ps_mgmt))) { + PRINTM(ERROR, "Copy to user failed!\n"); + LEAVE(); + return -EFAULT; + } + } + done: + LEAVE(); + return ret; +} + +/** + * @brief This function send bss_stop command to firmware + * + * @param priv A pointer to uap_private structure + * @return UAP_STATUS_SUCCESS on success, otherwise failure code + */ +static int +uap_bss_stop(uap_private * priv) +{ + int ret = UAP_STATUS_SUCCESS; + u32 CmdSize; + HostCmd_DS_GEN *cmd; + uap_adapter *Adapter = priv->adapter; + struct sk_buff *skb; + ENTER(); + if (Adapter->HardwareStatus != HWReady) { + PRINTM(ERROR, "uap_bss_stop:Hardware is not ready!\n"); + ret = -EFAULT; + goto done; + } + skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER); + if (!skb) { + PRINTM(ERROR, "No free skb\n"); + ret = -ENOMEM; + goto done; + } + CmdSize = sizeof(HostCmd_DS_GEN); + cmd = (HostCmd_DS_GEN *) (skb->data + INTF_HEADER_LEN); + cmd->Command = uap_cpu_to_le16(HOST_CMD_APCMD_BSS_STOP); + cmd->Size = uap_cpu_to_le16(CmdSize); + skb_put(skb, CmdSize + INTF_HEADER_LEN); + PRINTM(CMND, "APCMD_BSS_STOP\n"); + if (UAP_STATUS_SUCCESS != + uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP_TIMEOUT)) { + PRINTM(ERROR, "Fail to process cmd BSS_STOP\n"); + ret = -EFAULT; + goto done; + } + done: + LEAVE(); + return ret; +} + +/******************************************************** + Global Functions +********************************************************/ +/** + * @brief This function send soft_reset command to firmware + * + * @param priv A pointer to uap_private structure + * @return UAP_STATUS_SUCCESS on success, otherwise failure code + */ +int +uap_soft_reset(uap_private * priv) +{ + int ret = UAP_STATUS_SUCCESS; + u32 CmdSize; + HostCmd_DS_GEN *cmd; + uap_adapter *Adapter = priv->adapter; + struct sk_buff *skb; + ENTER(); + ret = uap_bss_stop(priv); + if (ret != UAP_STATUS_SUCCESS) + goto done; + skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER); + if (!skb) { + PRINTM(ERROR, "No free skb\n"); + ret = -ENOMEM; + goto done; + } + CmdSize = sizeof(HostCmd_DS_GEN); + cmd = (HostCmd_DS_GEN *) (skb->data + INTF_HEADER_LEN); + cmd->Command = uap_cpu_to_le16(HOST_CMD_APCMD_SOFT_RESET); + cmd->Size = uap_cpu_to_le16(CmdSize); + skb_put(skb, CmdSize + INTF_HEADER_LEN); + PRINTM(CMND, "APCMD_SOFT_RESET\n"); + if (UAP_STATUS_SUCCESS != + uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORSEND)) { + PRINTM(ERROR, "Fail to process cmd SOFT_RESET\n"); + ret = -EFAULT; + goto done; + } + Adapter->SurpriseRemoved = TRUE; + /* delay to allow hardware complete reset */ + os_sched_timeout(5); + if (priv->MediaConnected == TRUE) { + os_stop_queue(priv); + os_carrier_off(priv); + priv->MediaConnected = FALSE; + } + Adapter->CmdSize = 0; + Adapter->CmdWaitQWoken = TRUE; + wake_up_interruptible(&Adapter->cmdwait_q); + skb_queue_purge(&priv->adapter->tx_queue); + skb_queue_purge(&priv->adapter->cmd_queue); + done: + LEAVE(); + return ret; +} + +/** + * @brief This function processes received packet and forwards it + * to kernel/upper layer + * + * @param priv A pointer to uap_private + * @param skb A pointer to skb which includes the received packet + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE + */ +int +uap_process_rx_packet(uap_private * priv, struct sk_buff *skb) +{ + int ret = UAP_STATUS_SUCCESS; + RxPD *pRxPD; + ENTER(); + priv->adapter->ps_state = PS_STATE_AWAKE; + pRxPD = (RxPD *) skb->data; + endian_convert_RxPD(pRxPD); + DBG_HEXDUMP(DAT_D, "Rx", skb->data, MIN(skb->len, DATA_DUMP_LEN)); + skb_pull(skb, pRxPD->RxPktOffset); + priv->stats.rx_packets++; + priv->stats.rx_bytes += skb->len; + os_upload_rx_packet(priv, skb); + LEAVE(); + return ret; +} + +/** + * @brief This function opens the network device + * + * @param dev A pointer to net_device structure + * @return UAP_STATUS_SUCCESS + */ +static int +uap_open(struct net_device *dev) +{ + uap_private *priv = (uap_private *) (uap_private *) netdev_priv(dev); + uap_adapter *Adapter = priv->adapter; + int i = 0; + + ENTER(); + + /* On some systems the device open handler will be called before HW ready. */ + /* Use the following flag check and wait function to work around the issue. */ + while ((Adapter->HardwareStatus != HWReady) && + (i < MAX_WAIT_DEVICE_READY_COUNT)) { + i++; + os_sched_timeout(100); + } + if (i >= MAX_WAIT_DEVICE_READY_COUNT) { + PRINTM(FATAL, "HW not ready, uap_open() return failure\n"); + LEAVE(); + return UAP_STATUS_FAILURE; + } + + if (MODULE_GET == 0) + return UAP_STATUS_FAILURE; + + priv->open = TRUE; + if (priv->MediaConnected == TRUE) { + os_carrier_on(priv); + os_start_queue(priv); + } else { + os_stop_queue(priv); + os_carrier_off(priv); + } + LEAVE(); + return UAP_STATUS_SUCCESS; +} + +/** + * @brief This function closes the network device + * + * @param dev A pointer to net_device structure + * @return UAP_STATUS_SUCCESS + */ +static int +uap_close(struct net_device *dev) +{ + uap_private *priv = (uap_private *) netdev_priv(dev); + + ENTER(); + skb_queue_purge(&priv->adapter->tx_queue); + os_stop_queue(priv); + os_carrier_off(priv); + + MODULE_PUT; + priv->open = FALSE; + LEAVE(); + return UAP_STATUS_SUCCESS; +} + +/** + * @brief This function returns the network statistics + * + * @param dev A pointer to uap_private structure + * @return A pointer to net_device_stats structure + */ +static struct net_device_stats * +uap_get_stats(struct net_device *dev) +{ + uap_private *priv = (uap_private *) netdev_priv(dev); + + return &priv->stats; +} + +/** + * @brief This function sets the MAC address to firmware. + * + * @param dev A pointer to uap_private structure + * @param addr MAC address to set + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE + */ +static int +uap_set_mac_address(struct net_device *dev, void *addr) +{ + int ret = UAP_STATUS_SUCCESS; + uap_private *priv = (uap_private *) netdev_priv(dev); + struct sockaddr *pHwAddr = (struct sockaddr *) addr; + u32 CmdSize; + HostCmd_DS_COMMAND *cmd; + MrvlIEtypes_MacAddr_t *pMacAddrTlv; + uap_adapter *Adapter = priv->adapter; + struct sk_buff *skb; + + ENTER(); + + /* Dump MAC address */ + DBG_HEXDUMP(CMD_D, "Original MAC addr", dev->dev_addr, ETH_ALEN); + DBG_HEXDUMP(CMD_D, "New MAC addr", pHwAddr->sa_data, ETH_ALEN); + if (priv->open && (priv->MediaConnected == TRUE)) { + os_carrier_on(priv); + os_start_queue(priv); + } + skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER); + if (!skb) { + PRINTM(ERROR, "No free skb\n"); + LEAVE(); + return -ENOMEM; + } + CmdSize = + S_DS_GEN + sizeof(HostCmd_SYS_CONFIG) + sizeof(MrvlIEtypes_MacAddr_t); + cmd = (HostCmd_DS_COMMAND *) (skb->data + INTF_HEADER_LEN); + cmd->Command = uap_cpu_to_le16(HOST_CMD_APCMD_SYS_CONFIGURE); + cmd->Size = uap_cpu_to_le16(CmdSize); + cmd->params.sys_config.Action = uap_cpu_to_le16(ACTION_SET); + pMacAddrTlv = + (MrvlIEtypes_MacAddr_t *) ((u8 *) cmd + S_DS_GEN + + sizeof(HostCmd_SYS_CONFIG)); + pMacAddrTlv->Header.Type = uap_cpu_to_le16(MRVL_AP_MAC_ADDRESS_TLV_ID); + pMacAddrTlv->Header.Len = uap_cpu_to_le16(ETH_ALEN); + memcpy(pMacAddrTlv->ApMacAddr, pHwAddr->sa_data, ETH_ALEN); + skb_put(skb, CmdSize + INTF_HEADER_LEN); + PRINTM(CMND, "set_mac_address\n"); + if (UAP_STATUS_SUCCESS != + uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP_TIMEOUT)) { + PRINTM(ERROR, "Fail to set mac address\n"); + LEAVE(); + return -EFAULT; + } + if (!Adapter->CmdSize) { + PRINTM(ERROR, "Cmd Size is 0\n"); + LEAVE(); + return -EFAULT; + } + cmd = (HostCmd_DS_COMMAND *) Adapter->CmdBuf; + cmd->Result = uap_cpu_to_le16(cmd->Result); + if (cmd->Result != UAP_STATUS_SUCCESS) { + PRINTM(ERROR, "set mac addrress fail,cmd result=%x\n", cmd->Result); + ret = -EFAULT; + } else + memcpy(dev->dev_addr, pHwAddr->sa_data, ETH_ALEN); + LEAVE(); + return ret; +} + +/** + * @brief This function handles the timeout of packet + * transmission + * + * @param dev A pointer to net_device structure + * @return n/a + */ +static void +uap_tx_timeout(struct net_device *dev) +{ + uap_private *priv = (uap_private *) netdev_priv(dev); + + ENTER(); + + PRINTM(DATA, "Tx timeout\n"); + UpdateTransStart(dev); + priv->num_tx_timeout++; + priv->adapter->IntCounter++; + wake_up_interruptible(&priv->MainThread.waitQ); + + LEAVE(); +} + +/** + * @brief This function handles packet transmission + * + * @param skb A pointer to sk_buff structure + * @param dev A pointer to net_device structure + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE + */ +static int +uap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + uap_private *priv = (uap_private *) netdev_priv(dev); + int ret = UAP_STATUS_SUCCESS; + + ENTER(); + PRINTM(DATA, "Data <= kernel\n"); + DBG_HEXDUMP(DAT_D, "Tx", skb->data, MIN(skb->len, DATA_DUMP_LEN)); + /* skb sanity check */ + if (!skb->len || (skb->len > MRVDRV_MAXIMUM_ETH_PACKET_SIZE)) { + PRINTM(ERROR, "Tx Error: Bad skb length %d : %d\n", skb->len, + MRVDRV_MAXIMUM_ETH_PACKET_SIZE); + priv->stats.tx_dropped++; + kfree(skb); + goto done; + } + skb_queue_tail(&priv->adapter->tx_queue, skb); + wake_up_interruptible(&priv->MainThread.waitQ); + if (skb_queue_len(&priv->adapter->tx_queue) > TX_HIGH_WATERMARK) { + UpdateTransStart(dev); + os_stop_queue(priv); + } + done: + LEAVE(); + return ret; +} + +/** + * @brief ioctl function - entry point + * + * @param dev A pointer to net_device structure + * @param req A pointer to ifreq structure + * @param cmd command + * @return UAP_STATUS_SUCCESS--success, otherwise fail + */ +static int +uap_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd) +{ + int ret = UAP_STATUS_SUCCESS; + + ENTER(); + + PRINTM(CMND, "uap_do_ioctl: ioctl cmd = 0x%x\n", cmd); + + switch (cmd) { + case UAPHOSTCMD: + ret = uap_hostcmd_ioctl(dev, req); + break; + case UAP_POWER_MODE: + ret = uap_power_mode_ioctl(dev, req); + break; + default: + ret = -EINVAL; + break; + } + + LEAVE(); + return ret; +} + +/** + * @brief This function handles events generated by firmware + * + * @param priv A pointer to uap_private structure + * @param payload A pointer to payload buffer + * @param len Length of the payload + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE + */ +int +uap_process_event(uap_private * priv, u8 * payload, uint len) +{ + int ret = UAP_STATUS_SUCCESS; + uap_adapter *Adapter = priv->adapter; + struct sk_buff *skb = NULL; + struct nlmsghdr *nlh = NULL; + struct sock *sk = Adapter->nl_sk; + AP_Event *pEvent; + + ENTER(); + Adapter->ps_state = PS_STATE_AWAKE; + if (len > NL_MAX_PAYLOAD) { + PRINTM(ERROR, "event size is too big!!! len=%d\n", len); + ret = UAP_STATUS_FAILURE; + goto done; + } + pEvent = (AP_Event *) payload; + PRINTM(CMND, "Event: %d\n", pEvent->EventId); + switch (pEvent->EventId) { + case MICRO_AP_EV_ID_BSS_START: + memcpy(priv->uap_dev.netdev->dev_addr, pEvent->MacAddr, ETH_ALEN); + DBG_HEXDUMP(CMD_D, "BSS MAC addr", priv->uap_dev.netdev->dev_addr, + ETH_ALEN); + break; + case MICRO_AP_EV_BSS_ACTIVE: + // carrier on + priv->MediaConnected = TRUE; + os_carrier_on(priv); + os_start_queue(priv); + break; + case MICRO_AP_EV_BSS_IDLE: + os_stop_queue(priv); + os_carrier_off(priv); + priv->MediaConnected = FALSE; + break; + case EVENT_PS_AWAKE: + PRINTM(CMND, "UAP: PS_AWAKE\n"); + Adapter->ps_state = PS_STATE_AWAKE; + Adapter->WakeupTries = 0; + break; + case EVENT_PS_SLEEP: + PRINTM(CMND, "UAP: PS_SLEEP\n"); + Adapter->ps_state = PS_STATE_PRE_SLEEP; + break; + default: + break; + } + if ((pEvent->EventId == EVENT_PS_AWAKE) || + (pEvent->EventId == EVENT_PS_SLEEP)) + goto done; + if (sk) { + /* Allocate skb */ + if (!(skb = alloc_skb(NLMSG_SPACE(NL_MAX_PAYLOAD), GFP_ATOMIC))) { + PRINTM(ERROR, "Could not allocate skb for netlink.\n"); + ret = UAP_STATUS_FAILURE; + goto done; + } + nlh = (struct nlmsghdr *) skb->data; + nlh->nlmsg_len = NLMSG_SPACE(len); + + /* From kernel */ + nlh->nlmsg_pid = 0; + nlh->nlmsg_flags = 0; + + /* Data */ + skb_put(skb, nlh->nlmsg_len); + memcpy(NLMSG_DATA(nlh), payload, len); + + /* From Kernel */ + NETLINK_CB(skb).pid = 0; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) + /* Multicast message */ + NETLINK_CB(skb).dst_pid = 0; +#endif + + /* Multicast group number */ + NETLINK_CB(skb).dst_group = NL_MULTICAST_GROUP; + + /* Send message */ + netlink_broadcast(sk, skb, 0, NL_MULTICAST_GROUP, GFP_KERNEL); + + ret = UAP_STATUS_SUCCESS; + } else { + PRINTM(ERROR, "Could not send event through NETLINK. Link down.\n"); + ret = UAP_STATUS_FAILURE; + } + done: + LEAVE(); + return ret; +} + +/** + * @brief This function handles the interrupt. it will change PS + * state if applicable. it will wake up main_thread to handle + * the interrupt event as well. + * + * @param priv A pointer to uap_private structure + * @return n/a + */ +void +uap_interrupt(uap_private * priv) +{ + ENTER(); + priv->adapter->IntCounter++; + priv->adapter->WakeupTries = 0; + PRINTM(INFO, "*\n"); + wake_up_interruptible(&priv->MainThread.waitQ); + + LEAVE(); + +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) +/** Network device handlers */ +static const struct net_device_ops uap_netdev_ops = { + .ndo_open = uap_open, + .ndo_start_xmit = uap_hard_start_xmit, + .ndo_stop = uap_close, + .ndo_do_ioctl = uap_do_ioctl, + .ndo_set_mac_address = uap_set_mac_address, + .ndo_tx_timeout = uap_tx_timeout, + .ndo_get_stats = uap_get_stats, +}; +#endif + +/** + * @brief This function adds the card. it will probe the + * card, allocate the uap_priv and initialize the device. + * + * @param card A pointer to card + * @return A pointer to uap_private structure + */ +uap_private * +uap_add_card(void *card) +{ + struct net_device *dev = NULL; + uap_private *priv = NULL; + + ENTER(); + + if (OS_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem)) + goto exit_sem_err; + + /* Allocate an Ethernet device */ + if (!(dev = alloc_etherdev(sizeof(uap_private)))) { + PRINTM(FATAL, "Init ethernet device failed!\n"); + goto error; + } + priv = (uap_private *) netdev_priv(dev); + + /* Allocate name */ + if (dev_alloc_name(dev, "uap%d") < 0) { + PRINTM(ERROR, "Could not allocate device name!\n"); + goto error; + } + + /* Allocate buffer for uap_adapter */ + if (!(priv->adapter = kmalloc(sizeof(uap_adapter), GFP_KERNEL))) { + PRINTM(FATAL, "Allocate buffer for uap_adapter failed!\n"); + goto error; + } + memset(priv->adapter, 0, sizeof(uap_adapter)); + + priv->uap_dev.netdev = dev; + priv->uap_dev.card = card; + priv->MediaConnected = FALSE; + uappriv = priv; + ((struct sdio_mmc_card *) card)->priv = priv; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) + SET_MODULE_OWNER(dev); +#endif + + /* Setup the OS Interface to our functions */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) + dev->open = uap_open; + dev->stop = uap_close; + dev->hard_start_xmit = uap_hard_start_xmit; + dev->tx_timeout = uap_tx_timeout; + dev->get_stats = uap_get_stats; + dev->do_ioctl = uap_do_ioctl; + dev->set_mac_address = uap_set_mac_address; + dev->set_multicast_list = uap_set_multicast_list; +#else + dev->netdev_ops = &uap_netdev_ops; +#endif + dev->watchdog_timeo = MRVDRV_DEFAULT_WATCHDOG_TIMEOUT; + dev->hard_header_len += sizeof(TxPD) + INTF_HEADER_LEN; + dev->hard_header_len += HEADER_ALIGNMENT; +#define NETIF_F_DYNALLOC 16 + dev->features |= NETIF_F_DYNALLOC; + dev->flags |= IFF_BROADCAST | IFF_MULTICAST; + + /* Init SW */ + if (uap_init_sw(priv)) { + PRINTM(FATAL, "Software Init Failed\n"); + goto error; + } + + PRINTM(INFO, "Starting kthread...\n"); + priv->MainThread.priv = priv; + spin_lock_init(&priv->driver_lock); + uap_create_thread(uap_service_main_thread, &priv->MainThread, + "uap_main_service"); + while (priv->MainThread.pid == 0) { + os_sched_timeout(2); + } + + /* Register the device */ + if (sbi_register_dev(priv) < 0) { + PRINTM(FATAL, "Failed to register uap device!\n"); + goto err_registerdev; + } +#ifdef FW_DNLD_NEEDED + SET_NETDEV_DEV(dev, priv->hotplug_device); +#endif + + /* Init FW and HW */ + if (uap_init_fw(priv)) { + PRINTM(FATAL, "Firmware Init Failed\n"); + goto err_init_fw; + } + + priv->uap_dev.cmd_sent = FALSE; + priv->uap_dev.data_sent = FALSE; + + /* Get mac address from firmware */ + if (uap_get_mac_address(priv)) { + PRINTM(FATAL, "Fail to get mac address\n"); + goto err_init_fw; + } + /* Register network device */ + if (register_netdev(dev)) { + printk(KERN_ERR "Cannot register network device!\n"); + goto err_init_fw; + } +#ifdef CONFIG_PROC_FS + uap_proc_entry(priv, dev); + uap_debug_entry(priv, dev); +#endif /* CPNFIG_PROC_FS */ + OS_REL_SEMAPHORE(&AddRemoveCardSem); + + LEAVE(); + return priv; + err_init_fw: + sbi_unregister_dev(priv); + err_registerdev: + ((struct sdio_mmc_card *) card)->priv = NULL; + /* Stop the thread servicing the interrupts */ + priv->adapter->SurpriseRemoved = TRUE; + wake_up_interruptible(&priv->MainThread.waitQ); + while (priv->MainThread.pid) { + os_sched_timeout(1); + } + error: + if (dev) { + if (dev->reg_state == NETREG_REGISTERED) + unregister_netdev(dev); + if (priv->adapter) + uap_free_adapter(priv); + free_netdev(dev); + uappriv = NULL; + } + OS_REL_SEMAPHORE(&AddRemoveCardSem); + exit_sem_err: + LEAVE(); + return NULL; +} + +/** + * @brief This function removes the card. + * + * @param card A pointer to card + * @return UAP_STATUS_SUCCESS + */ +int +uap_remove_card(void *card) +{ + uap_private *priv = uappriv; + uap_adapter *Adapter; + struct net_device *dev; + + ENTER(); + + if (OS_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem)) + goto exit_sem_err; + + if (!priv || !(Adapter = priv->adapter)) { + goto exit_remove; + } + Adapter->SurpriseRemoved = TRUE; + if (Adapter->cmd_pending == TRUE) { + /* Wake up cmd Q */ + Adapter->CmdWaitQWoken = TRUE; + wake_up_interruptible(&Adapter->cmdwait_q); + } + dev = priv->uap_dev.netdev; + if (priv->MediaConnected == TRUE) { + os_stop_queue(priv); + os_carrier_off(priv); + priv->MediaConnected = FALSE; + } + Adapter->CmdSize = 0; + Adapter->CmdWaitQWoken = TRUE; + wake_up_interruptible(&Adapter->cmdwait_q); + skb_queue_purge(&priv->adapter->tx_queue); + skb_queue_purge(&priv->adapter->cmd_queue); + + /* Disable interrupts on the card */ + sbi_disable_host_int(priv); + PRINTM(INFO, "netdev_finish_unregister: %s%s.\n", dev->name, + (dev->features & NETIF_F_DYNALLOC) ? "" : ", old style"); + unregister_netdev(dev); + PRINTM(INFO, "Unregister finish\n"); + wake_up_interruptible(&priv->MainThread.waitQ); + while (priv->MainThread.pid) { + os_sched_timeout(1); + } + + if ((Adapter->nl_sk) && ((Adapter->nl_sk)->sk_socket)) { + sock_release((Adapter->nl_sk)->sk_socket); + Adapter->nl_sk = NULL; + } +#ifdef CONFIG_PROC_FS + uap_debug_remove(priv); + uap_proc_remove(priv); +#endif + sbi_unregister_dev(priv); + PRINTM(INFO, "Free Adapter\n"); + uap_free_adapter(priv); + priv->uap_dev.netdev = NULL; + free_netdev(dev); + uappriv = NULL; + + exit_remove: + OS_REL_SEMAPHORE(&AddRemoveCardSem); + exit_sem_err: + LEAVE(); + return UAP_STATUS_SUCCESS; +} + +/** + * @brief This function initializes module. + * + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE + */ +static int __init +uap_init_module(void) +{ + int ret = UAP_STATUS_SUCCESS; + ENTER(); + + OS_INIT_SEMAPHORE(&AddRemoveCardSem); + ret = sbi_register(); + LEAVE(); + return ret; +} + +/** + * @brief This function cleans module + * + * @return n/a + */ +static void __exit +uap_cleanup_module(void) +{ + ENTER(); + + if (OS_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem)) + goto exit_sem_err; + + if ((uappriv) && (uappriv->adapter)) { + uap_func_shutdown(uappriv); + } + OS_REL_SEMAPHORE(&AddRemoveCardSem); + exit_sem_err: + sbi_unregister(); + LEAVE(); +} + +module_init(uap_init_module); +module_exit(uap_cleanup_module); +module_param(helper_name, charp, 0); +MODULE_PARM_DESC(helper_name, "Helper name"); +module_param(fw_name, charp, 0); +MODULE_PARM_DESC(fw_name, "Firmware name"); + +MODULE_DESCRIPTION("M-UAP Driver"); +MODULE_AUTHOR("Marvell International Ltd."); +MODULE_VERSION(DRIVER_VERSION); +MODULE_LICENSE("GPL"); diff --git a/libertas_uap/uap_proc.c b/libertas_uap/uap_proc.c new file mode 100644 index 0000000..a28a9a6 --- /dev/null +++ b/libertas_uap/uap_proc.c @@ -0,0 +1,296 @@ +/** @file uap_proc.c + * @brief This file contains functions for proc file. + * + * Copyright (C) 2008-2009, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available along with the File in the gpl.txt file or by writing to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ +#ifdef CONFIG_PROC_FS +#include "uap_headers.h" + +/** /proc directory root */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) +#define PROC_DIR NULL +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) +#define PROC_DIR &proc_root +#else +#define PROC_DIR proc_net +#endif + +/******************************************************** + Local Variables +********************************************************/ + +/******************************************************** + Global Variables +********************************************************/ + +/******************************************************** + Local Functions +********************************************************/ + +/** + * @brief proc read function + * + * @param page pointer to buffer + * @param start read data starting position + * @param offset offset + * @param count counter + * @param eof end of file flag + * @param data data to output + * @return number of output data + */ +static int +uap_proc_read(char *page, char **start, off_t offset, + int count, int *eof, void *data) +{ + int i; + char *p = page; + struct net_device *netdev = data; + struct netdev_hw_addr *ha; + char fmt[64]; + uap_private *priv = (uap_private *) netdev_priv(netdev); + + if (offset != 0) { + *eof = 1; + goto exit; + } + + strcpy(fmt, DRIVER_VERSION); + + p += sprintf(p, "driver_name = " "\"uap\"\n"); + p += sprintf(p, "driver_version = %s-(FP%s)", fmt, FPNUM); + p += sprintf(p, "\nInterfaceName=\"%s\"\n", netdev->name); + p += sprintf(p, "State=\"%s\"\n", + ((priv->MediaConnected == + FALSE) ? "Disconnected" : "Connected")); + p += sprintf(p, "MACAddress=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n", + netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2], + netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]); + i = 0; + netdev_for_each_mc_addr(ha, netdev) { + ++i; + } + p += sprintf(p, "MCCount=\"%d\"\n", i); + + /* + * Put out the multicast list + */ + i = 0; + netdev_for_each_mc_addr(ha, netdev) { + p += sprintf(p, + "MCAddr[%d]=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n", + i++, + ha->addr[0], ha->addr[1], + ha->addr[2], ha->addr[3], + ha->addr[4], ha->addr[5]); + } + + p += sprintf(p, "num_tx_bytes = %lu\n", priv->stats.tx_bytes); + p += sprintf(p, "num_rx_bytes = %lu\n", priv->stats.rx_bytes); + p += sprintf(p, "num_tx_pkts = %lu\n", priv->stats.tx_packets); + p += sprintf(p, "num_rx_pkts = %lu\n", priv->stats.rx_packets); + p += sprintf(p, "num_tx_pkts_dropped = %lu\n", priv->stats.tx_dropped); + p += sprintf(p, "num_rx_pkts_dropped = %lu\n", priv->stats.rx_dropped); + p += sprintf(p, "num_tx_pkts_err = %lu\n", priv->stats.tx_errors); + p += sprintf(p, "num_rx_pkts_err = %lu\n", priv->stats.rx_errors); + p += sprintf(p, "num_tx_timeout = %u\n", priv->num_tx_timeout); + p += sprintf(p, "carrier %s\n", + ((netif_carrier_ok(priv->uap_dev.netdev)) ? "on" : "off")); + p += sprintf(p, "tx queue %s\n", + ((netif_queue_stopped(priv->uap_dev.netdev)) ? "stopped" : + "started")); + + exit: + return (p - page); +} + +/** + * @brief hwstatus proc write function + * + * @param f file pointer + * @param buf pointer to data buffer + * @param cnt data number to write + * @param data data to write + * @return number of data + */ +static int +uap_hwstatus_write(struct file *f, const char *buf, unsigned long cnt, + void *data) +{ + struct net_device *netdev = data; + uap_private *priv = (uap_private *) netdev_priv(netdev); + char databuf[10]; + int hwstatus; + MODULE_GET; + if (cnt > 10) { + MODULE_PUT; + return cnt; + } + if (copy_from_user(databuf, buf, cnt)) { + MODULE_PUT; + return 0; + } + hwstatus = string_to_number(databuf); + switch (hwstatus) { + case HWReset: + PRINTM(MSG, "reset hw\n"); + uap_soft_reset(priv); + priv->adapter->HardwareStatus = HWReset; + break; + default: + break; + } + MODULE_PUT; + return cnt; +} + +/** + * @brief hwstatus proc read function + * + * @param page pointer to buffer + * @param s read data starting position + * @param off offset + * @param cnt counter + * @param eof end of file flag + * @param data data to output + * @return number of output data + */ +static int +uap_hwstatus_read(char *page, char **s, off_t off, int cnt, int *eof, + void *data) +{ + char *p = page; + struct net_device *netdev = data; + uap_private *priv = (uap_private *) netdev_priv(netdev); + MODULE_GET; + p += sprintf(p, "%d\n", priv->adapter->HardwareStatus); + MODULE_PUT; + return p - page; +} + +/******************************************************** + Global Functions +********************************************************/ +/** + * @brief create uap proc file + * + * @param priv pointer uap_private + * @param dev pointer net_device + * @return N/A + */ +void +uap_proc_entry(uap_private * priv, struct net_device *dev) +{ + struct proc_dir_entry *r = PROC_DIR; + + PRINTM(INFO, "Creating Proc Interface\n"); + /* Check if uap directory already exists */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) + for (r = r->subdir; r; r = r->next) { + if (r->namelen && !strcmp("uap", r->name)) { + /* Directory exists */ + PRINTM(WARN, "proc directory already exists!\n"); + priv->proc_uap = r; + break; + } + } +#endif + if (!priv->proc_uap) { + priv->proc_uap = proc_mkdir("uap", PROC_DIR); + if (!priv->proc_uap) + return; + else + atomic_set(&priv->proc_uap->count, 1); + } else { + atomic_inc(&priv->proc_uap->count); + } + priv->proc_entry = proc_mkdir(dev->name, priv->proc_uap); + + if (priv->proc_entry) { + r = create_proc_read_entry("info", 0, priv->proc_entry, uap_proc_read, + dev); + r = create_proc_entry("hwstatus", 0644, priv->proc_entry); + if (r) { + r->data = dev; + r->read_proc = uap_hwstatus_read; + r->write_proc = uap_hwstatus_write; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) + r->owner = THIS_MODULE; +#endif + } else + PRINTM(MSG, "Fail to create proc hwstatus\n"); + } +} + +/** + * @brief remove proc file + * + * @param priv pointer uap_private + * @return N/A + */ +void +uap_proc_remove(uap_private * priv) +{ + if (priv->proc_uap) { + if (priv->proc_entry) { + remove_proc_entry("info", priv->proc_entry); + remove_proc_entry("hwstatus", priv->proc_entry); + } + remove_proc_entry(priv->uap_dev.netdev->name, priv->proc_uap); + atomic_dec(&priv->proc_uap->count); + if (atomic_read(&(priv->proc_uap->count)) == 0) + remove_proc_entry("uap", PROC_DIR); + } +} + +/** + * @brief convert string to number + * + * @param s pointer to numbered string + * @return converted number from string s + */ +int +string_to_number(char *s) +{ + int r = 0; + int base = 0; + int pn = 1; + + if (strncmp(s, "-", 1) == 0) { + pn = -1; + s++; + } + if ((strncmp(s, "0x", 2) == 0) || (strncmp(s, "0X", 2) == 0)) { + base = 16; + s += 2; + } else + base = 10; + + for (s = s; *s != 0; s++) { + if ((*s >= '0') && (*s <= '9')) + r = (r * base) + (*s - '0'); + else if ((*s >= 'A') && (*s <= 'F')) + r = (r * base) + (*s - 'A' + 10); + else if ((*s >= 'a') && (*s <= 'f')) + r = (r * base) + (*s - 'a' + 10); + else + break; + } + + return (r * pn); +} + +#endif diff --git a/libertas_uap/uap_sdio_mmc.c b/libertas_uap/uap_sdio_mmc.c new file mode 100644 index 0000000..86f55b5 --- /dev/null +++ b/libertas_uap/uap_sdio_mmc.c @@ -0,0 +1,1428 @@ +/** @file uap_sdio_mmc.c + * @brief This file contains SDIO IF (interface) module + * related functions. + * + * Copyright (C) 2007-2009, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available along with the File in the gpl.txt file or by writing to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ +/**************************************************** +Change log: +****************************************************/ + +#include "uap_sdio_mmc.h" + +#include + +/** define SDIO block size */ +/* We support up to 480-byte block size due to FW buffer limitation. */ +#define SD_BLOCK_SIZE 256 + +/** define allocated buffer size */ +#define ALLOC_BUF_SIZE (((MAX(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, \ + MRVDRV_SIZE_OF_CMD_BUFFER) + INTF_HEADER_LEN \ + + SD_BLOCK_SIZE - 1) / SD_BLOCK_SIZE) * SD_BLOCK_SIZE) + +/** Max retry number of CMD53 write */ +#define MAX_WRITE_IOMEM_RETRY 2 + +/******************************************************** + Local Variables +********************************************************/ + +/** SDIO Rx unit */ +static u8 sdio_rx_unit = 0; + +/**Interrupt status */ +static u8 sd_ireg = 0; +/******************************************************** + Global Variables +********************************************************/ +extern u8 *helper_name; +extern u8 *fw_name; +/** Default helper name */ +#define DEFAULT_HELPER_NAME "mrvl/helper_sd.bin" +/** Default firmware name */ +#define DEFAULT_FW_NAME "mrvl/sd8688_ap.bin" + +/******************************************************** + Local Functions +********************************************************/ +/** + * @brief This function reads the IO register. + * + * @param priv A pointer to uap_private structure + * @param reg register to be read + * @param dat A pointer to variable that keeps returned value + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE + */ +static int +sbi_read_ioreg(uap_private * priv, u32 reg, u8 * dat) +{ + struct sdio_mmc_card *card; + int ret = UAP_STATUS_FAILURE; + + ENTER(); + + card = priv->uap_dev.card; + if (!card || !card->func) { + PRINTM(ERROR, "sbi_read_ioreg(): card or function is NULL!\n"); + goto done; + } + + *dat = sdio_readb(card->func, reg, &ret); + if (ret) { + PRINTM(ERROR, "sbi_read_ioreg(): sdio_readb failed! ret=%d\n", ret); + goto done; + } + + PRINTM(INFO, "sbi_read_ioreg() priv=%p func=%d reg=%#x dat=%#x\n", priv, + card->func->num, reg, *dat); + + done: + LEAVE(); + return ret; +} + +/** + * @brief This function writes the IO register. + * + * @param priv A pointer to uap_private structure + * @param reg register to be written + * @param dat the value to be written + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE + */ +static int +sbi_write_ioreg(uap_private * priv, u32 reg, u8 dat) +{ + struct sdio_mmc_card *card; + int ret = UAP_STATUS_FAILURE; + + ENTER(); + + card = priv->uap_dev.card; + if (!card || !card->func) { + PRINTM(ERROR, "sbi_write_ioreg(): card or function is NULL!\n"); + goto done; + } + + PRINTM(INFO, "sbi_write_ioreg() priv=%p func=%d reg=%#x dat=%#x\n", priv, + card->func->num, reg, dat); + + sdio_writeb(card->func, dat, reg, &ret); + if (ret) { + PRINTM(ERROR, "sbi_write_ioreg(): sdio_readb failed! ret=%d\n", ret); + goto done; + } + + done: + LEAVE(); + return ret; +} + +/** + * @brief This function get rx_unit value + * + * @param priv A pointer to uap_private structure + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE + */ +static int +sd_get_rx_unit(uap_private * priv) +{ + int ret = UAP_STATUS_SUCCESS; + u8 reg; + + ENTER(); + + ret = sbi_read_ioreg(priv, CARD_RX_UNIT_REG, ®); + if (ret == UAP_STATUS_SUCCESS) + sdio_rx_unit = reg; + + LEAVE(); + return ret; +} + +/** + * @brief This function reads rx length + * + * @param priv A pointer to uap_private structure + * @param dat A pointer to keep returned data + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE + */ +static int +sd_read_rx_len(uap_private * priv, u16 * dat) +{ + int ret = UAP_STATUS_SUCCESS; + u8 reg; + + ENTER(); + + ret = sbi_read_ioreg(priv, CARD_RX_LEN_REG, ®); + if (ret == UAP_STATUS_SUCCESS) + *dat = (u16) reg << sdio_rx_unit; + + LEAVE(); + return ret; +} + +/** + * @brief This function reads fw status registers + * + * @param priv A pointer to uap_private structure + * @param dat A pointer to keep returned data + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE + */ +static int +sd_read_firmware_status(uap_private * priv, u16 * dat) +{ + int ret = UAP_STATUS_SUCCESS; + u8 fws0; + u8 fws1; + + ENTER(); + + ret = sbi_read_ioreg(priv, CARD_FW_STATUS0_REG, &fws0); + if (ret < 0) { + LEAVE(); + return UAP_STATUS_FAILURE; + } + + ret = sbi_read_ioreg(priv, CARD_FW_STATUS1_REG, &fws1); + if (ret < 0) { + LEAVE(); + return UAP_STATUS_FAILURE; + } + + *dat = (((u16) fws1) << 8) | fws0; + + LEAVE(); + return UAP_STATUS_SUCCESS; +} + +/** + * @brief This function polls the card status register. + * + * @param priv A pointer to uap_private structure + * @param bits the bit mask + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE + */ +static int +mv_sdio_poll_card_status(uap_private * priv, u8 bits) +{ + int tries; + u8 cs; + + ENTER(); + + for (tries = 0; tries < MAX_POLL_TRIES; tries++) { + if (sbi_read_ioreg(priv, CARD_STATUS_REG, &cs) < 0) + break; + else if ((cs & bits) == bits) { + LEAVE(); + return UAP_STATUS_SUCCESS; + } + udelay(10); + } + + PRINTM(WARN, "mv_sdio_poll_card_status failed, tries = %d\n", tries); + + LEAVE(); + return UAP_STATUS_FAILURE; +} + +/** + * @brief This function set the sdio bus width. + * + * @param priv A pointer to uap_private structure + * @param mode 1--1 bit mode, 4--4 bit mode + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE + */ +#if 0 +static int +sdio_set_bus_width(uap_private * priv, u8 mode) +{ + ENTER(); + LEAVE(); + return UAP_STATUS_SUCCESS; +} +#endif + +/** + * @brief This function reads data from the card. + * + * @param priv A pointer to uap_private structure + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE + */ +static int +sd_card_to_host(uap_private * priv) +{ + int ret = UAP_STATUS_SUCCESS; + u16 buf_len = 0; + int buf_block_len; + int blksz; + struct sk_buff *skb = NULL; + u16 type; + u8 *payload = NULL; + struct sdio_mmc_card *card = priv->uap_dev.card; + + ENTER(); + + if (!card || !card->func) { + PRINTM(ERROR, "card or function is NULL!\n"); + ret = UAP_STATUS_FAILURE; + goto exit; + } + + /* Read the length of data to be transferred */ + ret = sd_read_rx_len(priv, &buf_len); + if (ret < 0) { + PRINTM(ERROR, "card_to_host, read scratch reg failed\n"); + ret = UAP_STATUS_FAILURE; + goto exit; + } + + /* Allocate buffer */ + blksz = SD_BLOCK_SIZE; + buf_block_len = (buf_len + blksz - 1) / blksz; + if (buf_len <= INTF_HEADER_LEN || (buf_block_len * blksz) > ALLOC_BUF_SIZE) { + PRINTM(ERROR, "card_to_host, invalid packet length: %d\n", buf_len); + ret = UAP_STATUS_FAILURE; + goto exit; + } +#ifdef PXA3XX_DMA_ALIGN + skb = dev_alloc_skb(buf_block_len * blksz + PXA3XX_DMA_ALIGNMENT); +#else + skb = dev_alloc_skb(buf_block_len * blksz); +#endif + if (skb == NULL) { + PRINTM(WARN, "No free skb\n"); + goto exit; + } +#ifdef PXA3XX_DMA_ALIGN + if ((u32) skb->data & (PXA3XX_DMA_ALIGNMENT - 1)) { + skb_put(skb, (u32) skb->data & (PXA3XX_DMA_ALIGNMENT - 1)); + skb_pull(skb, (u32) skb->data & (PXA3XX_DMA_ALIGNMENT - 1)); + } +#endif /* PXA3XX_DMA_ALIGN */ + + payload = skb->tail; + ret = sdio_readsb(card->func, payload, priv->uap_dev.ioport, + buf_block_len * blksz); + if (ret < 0) { + PRINTM(ERROR, "card_to_host, read iomem failed: %d\n", ret); + ret = UAP_STATUS_FAILURE; + goto exit; + } + HEXDUMP("SDIO Blk Rd", payload, blksz * buf_block_len); + /* + * This is SDIO specific header + * u16 length, + * u16 type (MV_TYPE_DAT = 0, MV_TYPE_CMD = 1, MV_TYPE_EVENT = 3) + */ + buf_len = uap_le16_to_cpu(*(u16 *) & payload[0]); + type = uap_le16_to_cpu(*(u16 *) & payload[2]); + switch (type) { + case MV_TYPE_EVENT: + skb_put(skb, buf_len); + skb_pull(skb, INTF_HEADER_LEN); + uap_process_event(priv, skb->data, skb->len); + kfree_skb(skb); + skb = NULL; + break; + case MV_TYPE_CMD: + skb_put(skb, buf_len); + skb_pull(skb, INTF_HEADER_LEN); + priv->adapter->cmd_pending = FALSE; + if (priv->adapter->cmd_wait_option == + HostCmd_OPTION_WAITFORRSP_SLEEPCONFIRM) { + priv->adapter->cmd_wait_option = FALSE; + uap_process_sleep_confirm_resp(priv, skb->data, skb->len); + } else if (priv->adapter->cmd_wait_option) { + memcpy(priv->adapter->CmdBuf, skb->data, skb->len); + priv->adapter->CmdSize = skb->len; + priv->adapter->cmd_wait_option = FALSE; + priv->adapter->CmdWaitQWoken = TRUE; + wake_up_interruptible(&priv->adapter->cmdwait_q); + } + kfree_skb(skb); + skb = NULL; + break; + case MV_TYPE_DAT: + skb_put(skb, buf_len); + skb_pull(skb, INTF_HEADER_LEN); + uap_process_rx_packet(priv, skb); + break; + default: + priv->stats.rx_errors++; + priv->stats.rx_dropped++; + /* Driver specified event and command resp should be handle here */ + PRINTM(INFO, "Unknown PKT type:%d\n", type); + kfree_skb(skb); + skb = NULL; + break; + } + exit: + if (ret) { + if (skb) + kfree_skb(skb); + } + + LEAVE(); + return ret; +} + +/** + * @brief This function enables the host interrupts mask + * + * @param priv A pointer to uap_private structure + * @param mask the interrupt mask + * @return UAP_STATUS_SUCCESS + */ +static int +enable_host_int_mask(uap_private * priv, u8 mask) +{ + int ret = UAP_STATUS_SUCCESS; + + ENTER(); + + /* Simply write the mask to the register */ + ret = sbi_write_ioreg(priv, HOST_INT_MASK_REG, mask); + + if (ret) { + PRINTM(WARN, "Unable to enable the host interrupt!\n"); + ret = UAP_STATUS_FAILURE; + } + + LEAVE(); + return ret; +} + +/** @brief This function disables the host interrupts mask. + * + * @param priv A pointer to uap_private structure + * @param mask the interrupt mask + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE + */ +static int +disable_host_int_mask(uap_private * priv, u8 mask) +{ + int ret = UAP_STATUS_SUCCESS; + u8 host_int_mask; + + ENTER(); + + /* Read back the host_int_mask register */ + ret = sbi_read_ioreg(priv, HOST_INT_MASK_REG, &host_int_mask); + if (ret) { + ret = UAP_STATUS_FAILURE; + goto done; + } + + /* Update with the mask and write back to the register */ + host_int_mask &= ~mask; + ret = sbi_write_ioreg(priv, HOST_INT_MASK_REG, host_int_mask); + if (ret < 0) { + PRINTM(WARN, "Unable to diable the host interrupt!\n"); + ret = UAP_STATUS_FAILURE; + goto done; + } + + done: + LEAVE(); + return ret; +} + +/******************************************************** + Global Functions +********************************************************/ + +/** + * @brief This function handles the interrupt. + * + * @param func A pointer to sdio_func structure. + * @return n/a + */ +static void +sbi_interrupt(struct sdio_func *func) +{ + struct sdio_mmc_card *card; + uap_private *priv; + u8 ireg = 0; + int ret = UAP_STATUS_SUCCESS; + + ENTER(); + + card = sdio_get_drvdata(func); + if (!card || !card->priv) { + PRINTM(MSG, "%s: sbi_interrupt(%p) card or priv is NULL, card=%p\n", + __FUNCTION__, func, card); + LEAVE(); + return; + } + priv = card->priv; +#ifdef FW_WAKEUP_TIME + if ((priv->adapter->wt_pwrup_sending != 0L) && + (priv->adapter->wt_int == 0L)) + priv->adapter->wt_int = get_utimeofday(); +#endif + + ireg = sdio_readb(card->func, HOST_INTSTATUS_REG, &ret); + if (ret) { + PRINTM(WARN, "sdio_read_ioreg: read int status register failed\n"); + goto done; + } + if (ireg != 0) { + /* + * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS + * Clear the interrupt status register and re-enable the interrupt + */ + PRINTM(INFO, "sdio_ireg = 0x%x\n", ireg); + sdio_writeb(card->func, + ~(ireg) & (DN_LD_HOST_INT_STATUS | UP_LD_HOST_INT_STATUS), + HOST_INTSTATUS_REG, &ret); + if (ret) { + PRINTM(WARN, + "sdio_write_ioreg: clear int status register failed\n"); + goto done; + } + } + OS_INT_DISABLE; + sd_ireg |= ireg; + OS_INT_RESTORE; + + uap_interrupt(priv); + done: + LEAVE(); +} + +/** + * @brief This function probe the card + * + * @param func A pointer to sdio_func structure + * @param id A pointer to structure sd_device_id + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE + */ +static int +uap_probe(struct sdio_func *func, const struct sdio_device_id *id) +{ + int ret = UAP_STATUS_FAILURE; + struct sdio_mmc_card *card = NULL; + + ENTER(); + + PRINTM(MSG, "%s: vendor=0x%4.04X device=0x%4.04X class=%d function=%d\n", + __FUNCTION__, func->vendor, func->device, func->class, func->num); + + card = kzalloc(sizeof(struct sdio_mmc_card), GFP_KERNEL); + if (!card) { + ret = -ENOMEM; + goto done; + } + + card->func = func; + + if (!uap_add_card(card)) { + PRINTM(ERROR, "%s: uap_add_callback failed\n", __FUNCTION__); + kfree(card); + ret = UAP_STATUS_FAILURE; + goto done; + } + + ret = UAP_STATUS_SUCCESS; + + done: + LEAVE(); + return ret; +} + +/** + * @brief This function removes the card + * + * @param func A pointer to sdio_func structure + * @return N/A + */ +static void +uap_remove(struct sdio_func *func) +{ + struct sdio_mmc_card *card; + + ENTER(); + + if (func) { + card = sdio_get_drvdata(func); + if (card) { + uap_remove_card(card); + kfree(card); + } + } + + LEAVE(); +} + +#ifdef CONFIG_PM +/** + * @brief This function handles client driver suspend + * + * @param func A pointer to sdio_func structure + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE + */ +int +uap_suspend(struct sdio_func *func) +{ + ENTER(); + LEAVE(); + return 0; +} + +/** + * @brief This function handles client driver resume + * + * @param func A pointer to sdio_func structure + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE + */ +int +uap_resume(struct sdio_func *func) +{ + ENTER(); + LEAVE(); + return 0; +} +#endif + +/** Device ID for SD8688 */ +#define SD_DEVICE_ID_8688_UAP 0x9104 +/** UAP IDs */ +static const struct sdio_device_id uap_ids[] = { + {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SD_DEVICE_ID_8688_UAP)}, + {}, +}; + +MODULE_DEVICE_TABLE(sdio, uap_ids); + +static struct sdio_driver uap_sdio = { + .name = "uap_sdio", + .id_table = uap_ids, + .probe = uap_probe, + .remove = uap_remove, +#ifdef CONFIG_PM +/* .suspend = uap_suspend, */ +/* .resume = uap_resume, */ +#endif + +}; + +/** + * @brief This function registers the IF module in bus driver. + * + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE + */ +int __init +sbi_register() +{ + int ret = UAP_STATUS_SUCCESS; + + ENTER(); + + /* SDIO Driver Registration */ + if (sdio_register_driver(&uap_sdio) != 0) { + PRINTM(FATAL, "SDIO Driver Registration Failed \n"); + ret = UAP_STATUS_FAILURE; + } + + LEAVE(); + return ret; +} + +/** + * @brief This function de-registers the IF module in bus driver. + * + * @return n/a + */ +void __exit +sbi_unregister(void) +{ + ENTER(); + + /* SDIO Driver Unregistration */ + sdio_unregister_driver(&uap_sdio); + + LEAVE(); +} + +/** + * @brief This function checks the interrupt status and handle it accordingly. + * + * @param priv A pointer to uap_private structure + * @param ireg A pointer to variable that keeps returned value + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE + */ +int +sbi_get_int_status(uap_private * priv, u8 * ireg) +{ + int ret = UAP_STATUS_SUCCESS; + u8 sdio_ireg = 0; + struct sdio_mmc_card *card = priv->uap_dev.card; + + ENTER(); + + *ireg = 0; + OS_INT_DISABLE; + sdio_ireg = sd_ireg; + sd_ireg = 0; + OS_INT_RESTORE; + + sdio_claim_host(card->func); + + if (sdio_ireg & DN_LD_HOST_INT_STATUS) { /* tx_done INT */ + if (!priv->uap_dev.cmd_sent) { /* tx_done already received */ + PRINTM(INFO, + "warning: tx_done already received: tx_dnld_rdy=0x%x int status=0x%x\n", + priv->uap_dev.cmd_sent, sdio_ireg); + } else { + priv->uap_dev.cmd_sent = FALSE; + priv->uap_dev.data_sent = FALSE; + if ( (priv->uap_dev.netdev->reg_state == NETREG_REGISTERED) && (skb_queue_len(&priv->adapter->tx_queue) < TX_LOW_WATERMARK)) { + os_start_queue(priv); + } + } + } + if (sdio_ireg & UP_LD_HOST_INT_STATUS) { + sd_card_to_host(priv); + } + + *ireg = sdio_ireg; + ret = UAP_STATUS_SUCCESS; + sdio_release_host(card->func); + + LEAVE(); + return ret; +} + +/** + * @brief This function disables the host interrupts. + * + * @param priv A pointer to uap_private structure + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE + */ +int +sbi_disable_host_int(uap_private * priv) +{ + struct sdio_mmc_card *card = priv->uap_dev.card; + int ret; + + ENTER(); + + sdio_claim_host(card->func); + ret = disable_host_int_mask(priv, HIM_DISABLE); + sdio_release_host(card->func); + + LEAVE(); + return ret; +} + +/** + * @brief This function enables the host interrupts. + * + * @param priv A pointer to uap_private structure + * @return UAP_STATUS_SUCCESS + */ +int +sbi_enable_host_int(uap_private * priv) +{ + struct sdio_mmc_card *card = priv->uap_dev.card; + int ret; + + ENTER(); + + sdio_claim_host(card->func); + ret = enable_host_int_mask(priv, HIM_ENABLE); + sdio_release_host(card->func); + + LEAVE(); + return ret; +} + +/** + * @brief This function de-registers the device. + * + * @param priv A pointer to uap_private structure + * @return UAP_STATUS_SUCCESS + */ +int +sbi_unregister_dev(uap_private * priv) +{ + struct sdio_mmc_card *card = priv->uap_dev.card; + + ENTER(); + + if (!card || !card->func) { + PRINTM(ERROR, "Error: card or function is NULL!\n"); + goto done; + } + + sdio_claim_host(card->func); + sdio_release_irq(card->func); + sdio_disable_func(card->func); + sdio_release_host(card->func); + + sdio_set_drvdata(card->func, NULL); + + done: + LEAVE(); + return UAP_STATUS_SUCCESS; +} + +/** + * @brief This function registers the device. + * + * @param priv A pointer to uap_private structure + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE + */ +int +sbi_register_dev(uap_private * priv) +{ + int ret = UAP_STATUS_FAILURE; + u8 reg; + struct sdio_mmc_card *card = priv->uap_dev.card; + struct sdio_func *func; + + ENTER(); + + if (!card || !card->func) { + PRINTM(ERROR, "Error: card or function is NULL!\n"); + goto done; + } + + func = card->func; + + /* Initialize the private structure */ + priv->uap_dev.ioport = 0; + + sdio_claim_host(func); + + ret = sdio_enable_func(func); + if (ret) { + PRINTM(FATAL, "sdio_enable_func() failed: ret=%d\n", ret); + goto release_host; + } + + ret = sdio_claim_irq(func, sbi_interrupt); + if (ret) { + PRINTM(FATAL, "sdio_claim_irq failed: ret=%d\n", ret); + goto disable_func; + } + + /* Read the IO port */ + ret = sbi_read_ioreg(priv, IO_PORT_0_REG, ®); + if (ret) + goto release_irq; + else + priv->uap_dev.ioport |= reg; + + ret = sbi_read_ioreg(priv, IO_PORT_1_REG, ®); + if (ret) + goto release_irq; + else + priv->uap_dev.ioport |= (reg << 8); + + ret = sbi_read_ioreg(priv, IO_PORT_2_REG, ®); + if (ret) + goto release_irq; + else + priv->uap_dev.ioport |= (reg << 16); + + PRINTM(INFO, "SDIO FUNC #%d IO port: 0x%x\n", func->num, + priv->uap_dev.ioport); + + ret = sdio_set_block_size(card->func, SD_BLOCK_SIZE); + if (ret) { + PRINTM(ERROR, "%s: cannot set SDIO block size\n", __FUNCTION__); + ret = UAP_STATUS_FAILURE; + goto release_irq; + } + priv->hotplug_device = &func->dev; + + if (helper_name == NULL) { + helper_name = DEFAULT_HELPER_NAME; + } + if (fw_name == NULL) { + fw_name = DEFAULT_FW_NAME; + } + sdio_release_host(func); + + sdio_set_drvdata(func, card); + + ret = UAP_STATUS_SUCCESS; + goto done; + + release_irq: + sdio_release_irq(func); + disable_func: + sdio_disable_func(func); + release_host: + sdio_release_host(func); + + done: + LEAVE(); + return ret; +} + +/** + * @brief This function sends data to the card. + * + * @param priv A pointer to uap_private structure + * @param payload A pointer to the data/cmd buffer + * @param nb the length of data/cmd + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE + */ +int +sbi_host_to_card(uap_private * priv, u8 * payload, u16 nb) +{ + struct sdio_mmc_card *card = priv->uap_dev.card; + int ret = UAP_STATUS_SUCCESS; + int buf_block_len; + int blksz; + int i = 0; + u8 *buf = NULL; +#ifdef PXA3XX_DMA_ALIGN + void *tmpbuf = NULL; + int tmpbufsz; +#endif + + ENTER(); + + if (!card || !card->func) { + PRINTM(ERROR, "card or function is NULL!\n"); + LEAVE(); + return UAP_STATUS_FAILURE; + } + buf = payload; +#ifdef PXA3XX_DMA_ALIGN + if ((u32) payload & (PXA3XX_DMA_ALIGNMENT - 1)) { + tmpbufsz = ALIGN_SZ(nb, PXA3XX_DMA_ALIGNMENT); + tmpbuf = kmalloc(tmpbufsz, GFP_KERNEL); + memset(tmpbuf, 0, tmpbufsz); + /* Ensure 8-byte aligned CMD buffer */ + buf = (u8 *) ALIGN_ADDR(tmpbuf, PXA3XX_DMA_ALIGNMENT); + memcpy(buf, payload, nb); + } +#endif + /* Allocate buffer and copy payload */ + blksz = SD_BLOCK_SIZE; + buf_block_len = (nb + blksz - 1) / blksz; + sdio_claim_host(card->func); +#define MAX_WRITE_IOMEM_RETRY 2 + priv->uap_dev.cmd_sent = TRUE; + priv->uap_dev.data_sent = TRUE; + do { + /* Transfer data to card */ + ret = sdio_writesb(card->func, priv->uap_dev.ioport, buf, + buf_block_len * blksz); + if (ret < 0) { + i++; + PRINTM(ERROR, "host_to_card, write iomem (%d) failed: %d\n", i, + ret); + ret = UAP_STATUS_FAILURE; + if (i > MAX_WRITE_IOMEM_RETRY) + goto exit; + } else { + HEXDUMP("SDIO Blk Wr", payload, nb); + } + } while (ret == UAP_STATUS_FAILURE); + exit: + sdio_release_host(card->func); +#ifdef PXA3XX_DMA_ALIGN + if (tmpbuf) + kfree(tmpbuf); +#endif + if (ret == UAP_STATUS_FAILURE) { + priv->uap_dev.cmd_sent = FALSE; + priv->uap_dev.data_sent = FALSE; + } + LEAVE(); + return ret; +} + +/** + * @brief This function reads CIS information. + * + * @param priv A pointer to uap_private structure + * @param cisinfo A pointer to CIS information output buffer + * @param cislen A pointer to length of CIS info output buffer + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE + */ +#if 0 +static int +sbi_get_cis_info(uap_private * priv, void *cisinfo, int *cislen) +{ +#define CIS_PTR (0x8000) + struct sdio_mmc_card *card = priv->uap_dev.card; + unsigned int i, cis_ptr = CIS_PTR; + int ret = UAP_STATUS_FAILURE; + + ENTER(); + + if (!card || !card->func) { + PRINTM(ERROR, "sbi_get_cis_info(): card or function is NULL!\n"); + goto exit; + } +#define MAX_SDIO_CIS_INFO_LEN (256) + if (!cisinfo || (*cislen < MAX_SDIO_CIS_INFO_LEN)) { + PRINTM(WARN, "ERROR! get_cis_info: insufficient buffer passed\n"); + goto exit; + } + + *cislen = MAX_SDIO_CIS_INFO_LEN; + + sdio_claim_host(card->func); + + PRINTM(INFO, "cis_ptr=%#x\n", cis_ptr); + + /* Read the Tuple Data */ + for (i = 0; i < *cislen; i++) { + ((unsigned char *) cisinfo)[i] = + sdio_readb(card->func, cis_ptr + i, &ret); + if (ret) { + PRINTM(WARN, "get_cis_info error: ret=%d\n", ret); + ret = UAP_STATUS_FAILURE; + goto done; + } + PRINTM(INFO, "cisinfo[%d]=%#x\n", i, ((unsigned char *) cisinfo)[i]); + } + + done: + sdio_release_host(card->func); + exit: + LEAVE(); + return ret; +} +#endif +/** + * @brief This function downloads helper image to the card. + * + * @param priv A pointer to uap_private structure + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE + */ +int +sbi_prog_helper(uap_private * priv) +{ + struct sdio_mmc_card *card = priv->uap_dev.card; + u8 *helper = NULL; + int helperlen; + int ret = UAP_STATUS_SUCCESS; + void *tmphlprbuf = NULL; + int tmphlprbufsz; + u8 *hlprbuf; + int hlprblknow; + u32 tx_len; +#ifdef FW_DOWNLOAD_SPEED + u32 tv1, tv2; +#endif + + ENTER(); + + if (!card || !card->func) { + PRINTM(ERROR, "sbi_prog_helper(): card or function is NULL!\n"); + goto done; + } + + if (priv->fw_helper) { + helper = (u8 *) priv->fw_helper->data; + helperlen = priv->fw_helper->size; + } else { + PRINTM(MSG, "No helper image found! Terminating download.\n"); + LEAVE(); + return UAP_STATUS_FAILURE; + } + + PRINTM(INFO, "Downloading helper image (%d bytes), block size %d bytes\n", + helperlen, SD_BLOCK_SIZE); + +#ifdef FW_DOWNLOAD_SPEED + tv1 = get_utimeofday(); +#endif + +#ifdef PXA3XX_DMA_ALIGN + tmphlprbufsz = ALIGN_SZ(UAP_UPLD_SIZE, PXA3XX_DMA_ALIGNMENT); +#else /* !PXA3XX_DMA_ALIGN */ + tmphlprbufsz = UAP_UPLD_SIZE; +#endif /* !PXA3XX_DMA_ALIGN */ + tmphlprbuf = kmalloc(tmphlprbufsz, GFP_KERNEL); + if (!tmphlprbuf) { + PRINTM(ERROR, + "Unable to allocate buffer for helper. Terminating download\n"); + ret = UAP_STATUS_FAILURE; + goto done; + } + memset(tmphlprbuf, 0, tmphlprbufsz); +#ifdef PXA3XX_DMA_ALIGN + hlprbuf = (u8 *) ALIGN_ADDR(tmphlprbuf, PXA3XX_DMA_ALIGNMENT); +#else /* !PXA3XX_DMA_ALIGN */ + hlprbuf = (u8 *) tmphlprbuf; +#endif /* !PXA3XX_DMA_ALIGN */ + + sdio_claim_host(card->func); + + /* Perform helper data transfer */ + tx_len = (FIRMWARE_TRANSFER_NBLOCK * SD_BLOCK_SIZE) - INTF_HEADER_LEN; + hlprblknow = 0; + do { + /* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY bits */ + ret = mv_sdio_poll_card_status(priv, CARD_IO_READY | DN_LD_CARD_RDY); + if (ret < 0) { + PRINTM(FATAL, "Helper download poll status timeout @ %d\n", + hlprblknow); + goto done; + } + + /* More data? */ + if (hlprblknow >= helperlen) + break; + + /* Set blocksize to transfer - checking for last block */ + if (helperlen - hlprblknow < tx_len) + tx_len = helperlen - hlprblknow; + + /* Set length to the 4-byte header */ + *(u32 *) hlprbuf = uap_cpu_to_le32(tx_len); + + /* Copy payload to buffer */ + memcpy(&hlprbuf[INTF_HEADER_LEN], &helper[hlprblknow], tx_len); + + PRINTM(INFO, "."); + + /* Send data */ + ret = sdio_writesb(card->func, priv->uap_dev.ioport, + hlprbuf, FIRMWARE_TRANSFER_NBLOCK * SD_BLOCK_SIZE); + + if (ret < 0) { + PRINTM(FATAL, "IO error during helper download @ %d\n", hlprblknow); + goto done; + } + + hlprblknow += tx_len; + } while (TRUE); + +#ifdef FW_DOWNLOAD_SPEED + tv2 = get_utimeofday(); + PRINTM(INFO, "helper: %ld.%03ld.%03ld ", tv1 / 1000000, + (tv1 % 1000000) / 1000, tv1 % 1000); + PRINTM(INFO, " -> %ld.%03ld.%03ld ", tv2 / 1000000, (tv2 % 1000000) / 1000, + tv2 % 1000); + tv2 -= tv1; + PRINTM(INFO, " == %ld.%03ld.%03ld\n", tv2 / 1000000, (tv2 % 1000000) / 1000, + tv2 % 1000); +#endif + + /* Write last EOF data */ + PRINTM(INFO, "\nTransferring helper image EOF block\n"); + memset(hlprbuf, 0x0, SD_BLOCK_SIZE); + ret = sdio_writesb(card->func, priv->uap_dev.ioport, + hlprbuf, SD_BLOCK_SIZE); + + if (ret < 0) { + PRINTM(FATAL, "IO error in writing helper image EOF block\n"); + goto done; + } + + ret = UAP_STATUS_SUCCESS; + + done: + sdio_release_host(card->func); + if (tmphlprbuf) + kfree(tmphlprbuf); + + LEAVE(); + return ret; +} + +/** + * @brief This function downloads firmware image to the card. + * + * @param priv A pointer to uap_private structure + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE + */ +int +sbi_prog_fw_w_helper(uap_private * priv) +{ + struct sdio_mmc_card *card = priv->uap_dev.card; + u8 *firmware = NULL; + int firmwarelen; + u8 base0; + u8 base1; + int ret = UAP_STATUS_SUCCESS; + int offset; + void *tmpfwbuf = NULL; + int tmpfwbufsz; + u8 *fwbuf; + u16 len; + int txlen = 0; + int tx_blocks = 0; + int i = 0; + int tries = 0; +#ifdef FW_DOWNLOAD_SPEED + u32 tv1, tv2; +#endif + + ENTER(); + + if (!card || !card->func) { + PRINTM(ERROR, "sbi_prog_fw_w_helper(): card or function is NULL!\n"); + goto done; + } + + if (priv->firmware) { + firmware = (u8 *) priv->firmware->data; + firmwarelen = priv->firmware->size; + } else { + PRINTM(MSG, "No firmware image found! Terminating download.\n"); + LEAVE(); + return UAP_STATUS_FAILURE; + } + + PRINTM(INFO, "Downloading FW image (%d bytes)\n", firmwarelen); + +#ifdef FW_DOWNLOAD_SPEED + tv1 = get_utimeofday(); +#endif + +#ifdef PXA3XX_DMA_ALIGN + tmpfwbufsz = ALIGN_SZ(UAP_UPLD_SIZE, PXA3XX_DMA_ALIGNMENT); +#else /* PXA3XX_DMA_ALIGN */ + tmpfwbufsz = UAP_UPLD_SIZE; +#endif /* PXA3XX_DMA_ALIGN */ + tmpfwbuf = kmalloc(tmpfwbufsz, GFP_KERNEL); + if (!tmpfwbuf) { + PRINTM(ERROR, + "Unable to allocate buffer for firmware. Terminating download.\n"); + ret = UAP_STATUS_FAILURE; + goto done; + } + memset(tmpfwbuf, 0, tmpfwbufsz); +#ifdef PXA3XX_DMA_ALIGN + /* Ensure 8-byte aligned firmware buffer */ + fwbuf = (u8 *) ALIGN_ADDR(tmpfwbuf, PXA3XX_DMA_ALIGNMENT); +#else /* PXA3XX_DMA_ALIGN */ + fwbuf = (u8 *) tmpfwbuf; +#endif /* PXA3XX_DMA_ALIGN */ + + sdio_claim_host(card->func); + + /* Perform firmware data transfer */ + offset = 0; + do { + /* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY bits */ + ret = mv_sdio_poll_card_status(priv, CARD_IO_READY | DN_LD_CARD_RDY); + if (ret < 0) { + PRINTM(FATAL, "FW download with helper poll status timeout @ %d\n", + offset); + goto done; + } + + /* More data? */ + if (offset >= firmwarelen) + break; + + for (tries = 0; tries < MAX_POLL_TRIES; tries++) { + if ((ret = sbi_read_ioreg(priv, HOST_F1_RD_BASE_0, &base0)) < 0) { + PRINTM(WARN, "Dev BASE0 register read failed:" + " base0=0x%04X(%d). Terminating download.\n", base0, + base0); + ret = UAP_STATUS_FAILURE; + goto done; + } + if ((ret = sbi_read_ioreg(priv, HOST_F1_RD_BASE_1, &base1)) < 0) { + PRINTM(WARN, "Dev BASE1 register read failed:" + " base1=0x%04X(%d). Terminating download.\n", base1, + base1); + ret = UAP_STATUS_FAILURE; + goto done; + } + len = (((u16) base1) << 8) | base0; + + /* For SD8688 wait until the length is not 0, 1 or 2 before + downloading the first FW block, since BOOT code writes the + register to indicate the helper/FW download winner, the value + could be 1 or 2 (Func1 or Func2). */ + if ((len && offset) || (len > 2)) + break; + udelay(10); + } + + if (len == 0) + break; + else if (len > UAP_UPLD_SIZE) { + PRINTM(FATAL, "FW download failure @ %d, invalid length %d\n", + offset, len); + ret = UAP_STATUS_FAILURE; + goto done; + } + + txlen = len; + + if (len & BIT(0)) { + i++; + if (i > MAX_WRITE_IOMEM_RETRY) { + PRINTM(FATAL, + "FW download failure @ %d, over max retry count\n", + offset); + ret = UAP_STATUS_FAILURE; + goto done; + } + PRINTM(ERROR, "FW CRC error indicated by the helper:" + " len = 0x%04X, txlen = %d\n", len, txlen); + len &= ~BIT(0); + /* Setting this to 0 to resend from same offset */ + txlen = 0; + } else { + i = 0; + + /* Set blocksize to transfer - checking for last block */ + if (firmwarelen - offset < txlen) { + txlen = firmwarelen - offset; + } + PRINTM(INFO, "."); + + tx_blocks = (txlen + SD_BLOCK_SIZE - 1) / SD_BLOCK_SIZE; + + /* Copy payload to buffer */ + memcpy(fwbuf, &firmware[offset], txlen); + } + + /* Send data */ + ret = sdio_writesb(card->func, priv->uap_dev.ioport, + fwbuf, tx_blocks * SD_BLOCK_SIZE); + + if (ret < 0) { + PRINTM(ERROR, "FW download, write iomem (%d) failed @ %d\n", i, + offset); + if (sbi_write_ioreg(priv, CONFIGURATION_REG, 0x04) < 0) { + PRINTM(ERROR, "write ioreg failed (CFG)\n"); + } + } + + offset += txlen; + } while (TRUE); + + PRINTM(INFO, "\nFW download over, size %d bytes\n", offset); + + ret = UAP_STATUS_SUCCESS; + done: +#ifdef FW_DOWNLOAD_SPEED + tv2 = get_utimeofday(); + PRINTM(INFO, "FW: %ld.%03ld.%03ld ", tv1 / 1000000, + (tv1 % 1000000) / 1000, tv1 % 1000); + PRINTM(INFO, " -> %ld.%03ld.%03ld ", tv2 / 1000000, + (tv2 % 1000000) / 1000, tv2 % 1000); + tv2 -= tv1; + PRINTM(INFO, " == %ld.%03ld.%03ld\n", tv2 / 1000000, + (tv2 % 1000000) / 1000, tv2 % 1000); +#endif + sdio_release_host(card->func); + if (tmpfwbuf) + kfree(tmpfwbuf); + + LEAVE(); + return ret; +} + +/** + * @brief This function checks if the firmware is ready to accept + * command or not. + * + * @param priv A pointer to uap_private structure + * @param pollnum Poll number + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE + */ +int +sbi_check_fw_status(uap_private * priv, int pollnum) +{ + struct sdio_mmc_card *card = priv->uap_dev.card; + int ret = UAP_STATUS_SUCCESS; + u16 firmwarestat; + int tries; + + ENTER(); + + sdio_claim_host(card->func); + + /* Wait for firmware initialization event */ + for (tries = 0; tries < pollnum; tries++) { + if ((ret = sd_read_firmware_status(priv, &firmwarestat)) < 0) + continue; + if (firmwarestat == FIRMWARE_READY) { + ret = UAP_STATUS_SUCCESS; + break; + } else { + mdelay(10); + ret = UAP_STATUS_FAILURE; + } + } + + if (ret < 0) + goto done; + + ret = UAP_STATUS_SUCCESS; + sd_get_rx_unit(priv); + + done: + sdio_release_host(card->func); + + LEAVE(); + return ret; +} + +/** + * @brief This function set bus clock on/off + * + * @param priv A pointer to uap_private structure + * @param option TRUE--on , FALSE--off + * @return UAP_STATUS_SUCCESS + */ +#if 0 +static int +sbi_set_bus_clock(uap_private * priv, u8 option) +{ + ENTER(); + LEAVE(); + return UAP_STATUS_SUCCESS; +} +#endif + +/** + * @brief This function wakeup firmware + * + * @param priv A pointer to uap_private structure + * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE + */ +int +sbi_wakeup_firmware(uap_private * priv) +{ + struct sdio_mmc_card *card = priv->uap_dev.card; + int ret = UAP_STATUS_SUCCESS; + + ENTER(); + + if (!card || !card->func) { + PRINTM(ERROR, "card or function is NULL!\n"); + LEAVE(); + return UAP_STATUS_FAILURE; + } + sdio_claim_host(card->func); + sdio_writeb(card->func, HOST_POWER_UP, CONFIGURATION_REG, &ret); + sdio_release_host(card->func); + LEAVE(); + return ret; +} diff --git a/libertas_uap/uap_sdio_mmc.h b/libertas_uap/uap_sdio_mmc.h new file mode 100644 index 0000000..191c67f --- /dev/null +++ b/libertas_uap/uap_sdio_mmc.h @@ -0,0 +1,136 @@ +/** @file uap_sdio_mmc.h + * @brief This file contains SDIO IF (interface) module + * related macros, enum, and structure. + * + * Copyright (C) 2007-2009, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available along with the File in the gpl.txt file or by writing to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ +/**************************************************** +Change log: + 10/10/07: initial version +****************************************************/ + +#ifndef _UAP_SDIO_MMC_H +#define _UAP_SDIO_MMC_H + +#include +#include +#include +#include + +#include "uap_headers.h" + +/** The number of times to try when waiting for downloaded firmware to + become active. (polling the scratch register). */ +#define MAX_FIRMWARE_POLL_TRIES 100 + +/** Firmware ready */ +#define FIRMWARE_READY 0xfedc + +/** Number of firmware blocks to transfer */ +#define FIRMWARE_TRANSFER_NBLOCK 2 + +/* Host Control Registers */ +/** Host Control Registers : I/O port 0 */ +#define IO_PORT_0_REG 0x00 +/** Host Control Registers : I/O port 1 */ +#define IO_PORT_1_REG 0x01 +/** Host Control Registers : I/O port 2 */ +#define IO_PORT_2_REG 0x02 + +/** Host Control Registers : Configuration */ +#define CONFIGURATION_REG 0x03 +/** Host Control Registers : Host without Command 53 finish host */ +#define HOST_WO_CMD53_FINISH_HOST (0x1U << 2) +/** Host Control Registers : Host power up */ +#define HOST_POWER_UP (0x1U << 1) +/** Host Control Registers : Host power down */ +#define HOST_POWER_DOWN (0x1U << 0) + +/** Host Control Registers : Host interrupt mask */ +#define HOST_INT_MASK_REG 0x04 +/** Host Control Registers : Upload host interrupt mask */ +#define UP_LD_HOST_INT_MASK (0x1U) +/** Host Control Registers : Download host interrupt mask */ +#define DN_LD_HOST_INT_MASK (0x2U) +/** Enable Host interrupt mask */ +#define HIM_ENABLE (UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK) +/** Disable Host interrupt mask */ +#define HIM_DISABLE 0xff + +/** Host Control Registers : Host interrupt status */ +#define HOST_INTSTATUS_REG 0x05 +/** Host Control Registers : Upload host interrupt status */ +#define UP_LD_HOST_INT_STATUS (0x1U) +/** Host Control Registers : Download host interrupt status */ +#define DN_LD_HOST_INT_STATUS (0x2U) + +/** Host F1 read base 0 */ +#define HOST_F1_RD_BASE_0 0x10 +/** Host F1 read base 1 */ +#define HOST_F1_RD_BASE_1 0x11 + +/** Card Control Registers : Card status register */ +#define CARD_STATUS_REG 0x20 +/** Card Control Registers : Card I/O ready */ +#define CARD_IO_READY (0x1U << 3) +/** Card Control Registers : CIS card ready */ +#define CIS_CARD_RDY (0x1U << 2) +/** Card Control Registers : Upload card ready */ +#define UP_LD_CARD_RDY (0x1U << 1) +/** Card Control Registers : Download card ready */ +#define DN_LD_CARD_RDY (0x1U << 0) + +/** Card Control Registers : Card OCR 0 register */ +#define CARD_OCR_0_REG 0x34 +/** Card Control Registers : Card OCR 1 register */ +#define CARD_OCR_1_REG 0x35 + +/** Firmware status 0 register */ +#define CARD_FW_STATUS0_REG 0x40 +/** Firmware status 1 register */ +#define CARD_FW_STATUS1_REG 0x41 +/** Rx length register */ +#define CARD_RX_LEN_REG 0x42 +/** Rx unit register */ +#define CARD_RX_UNIT_REG 0x43 + +/** Chip Id Register 0 */ +#define CARD_CHIP_ID_0_REG 0x801c +/** Chip Id Register 1 */ +#define CARD_CHIP_ID_1_REG 0x801d + +#ifdef PXA3XX_DMA_ALIGN +/** DMA alignment value for PXA3XX platforms */ +#define PXA3XX_DMA_ALIGNMENT 8 +/** Macros for Data Alignment : size */ +#define ALIGN_SZ(p, a) \ + (((p) + ((a) - 1)) & ~((a) - 1)) + +/** Macros for Data Alignment : address */ +#define ALIGN_ADDR(p, a) \ + ((((u32)(p)) + (((u32)(a)) - 1)) & ~(((u32)(a)) - 1)) +#endif /* PXA3XX_DMA_ALIGN */ + +struct sdio_mmc_card +{ + /** sdio_func structure pointer */ + struct sdio_func *func; + /** uap_private structure pointer */ + uap_private *priv; +}; + +#endif /* _UAP_SDIO_MMC_H */ diff --git a/modprobe_libertas_uap.conf b/modprobe_libertas_uap.conf new file mode 100644 index 0000000..0339023 --- /dev/null +++ b/modprobe_libertas_uap.conf @@ -0,0 +1,5 @@ +# blacklist competing modules for the same hardware +# used by libertas_uap (uap8xxx.ko) +blacklist libertas_sdio +blacklist libertas + diff --git a/uap8xxx.ko-3.2.9-kirkwood b/uap8xxx.ko-3.2.9-kirkwood new file mode 100644 index 0000000..540f74f Binary files /dev/null and b/uap8xxx.ko-3.2.9-kirkwood differ diff --git a/with-linux-3.2/0002-Driver-for-Marvell-Libertas-8688-SDIO-micro-AP-suppo-3.2.patch b/with-linux-3.2/0002-Driver-for-Marvell-Libertas-8688-SDIO-micro-AP-suppo-3.2.patch new file mode 100644 index 0000000..d725ef3 --- /dev/null +++ b/with-linux-3.2/0002-Driver-for-Marvell-Libertas-8688-SDIO-micro-AP-suppo-3.2.patch @@ -0,0 +1,31 @@ +--- ./drivers/net/wireless/libertas_uap/uap_main.c.orig 2012-01-05 02:04:22.082318156 -0700 ++++ ./drivers/net/wireless/libertas_uap/uap_main.c 2012-01-05 02:05:50.161341323 -0700 +@@ -1322,20 +1322,6 @@ uap_set_mac_address(struct net_device *d + } + + /** +- * @brief This function sets multicast addresses to firmware +- * +- * @param dev A pointer to net_device structure +- * @return n/a +- */ +-static void +-uap_set_multicast_list(struct net_device *dev) +-{ +- ENTER(); +-#warning uap_set_multicast_list not implemented. Expect problems with IPv6. +- LEAVE(); +-} +- +-/** + * @brief This function handles the timeout of packet + * transmission + * +@@ -1558,7 +1544,6 @@ static const struct net_device_ops uap_n + .ndo_set_mac_address = uap_set_mac_address, + .ndo_tx_timeout = uap_tx_timeout, + .ndo_get_stats = uap_get_stats, +- .ndo_set_multicast_list = uap_set_multicast_list, + }; + #endif + diff --git a/with-linux-3.2/linux-3.0-SDIO-micro-AP.patch b/with-linux-3.2/linux-3.0-SDIO-micro-AP.patch new file mode 100644 index 0000000..9998a51 --- /dev/null +++ b/with-linux-3.2/linux-3.0-SDIO-micro-AP.patch @@ -0,0 +1,5111 @@ +diff -Naupr linux-2.6.37/drivers/net/wireless/Kconfig linux-2.6.37-new/drivers/net/wireless/Kconfig +--- linux-2.6.37/drivers/net/wireless/Kconfig 2011-01-04 17:50:19.000000000 -0700 ++++ linux-2.6.37-new/drivers/net/wireless/Kconfig 2011-01-08 06:01:04.034836160 -0700 +@@ -51,6 +51,12 @@ config LIBERTAS_THINFIRM_USB + ---help--- + A driver for Marvell Libertas 8388 USB devices using thinfirm. + ++config LIBERTAS_UAP ++ tristate "Marvell Libertas 8688 micro-AP support" ++ depends on LIBERTAS && MMC ++ ---help--- ++ A driver for Marvell Libertas 8688 SDIO micro-AP support. ++ + config AIRO + tristate "Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards" + depends on ISA_DMA_API && (PCI || BROKEN) +diff -Naupr linux-2.6.37/drivers/net/wireless/Makefile linux-2.6.37-new/drivers/net/wireless/Makefile +--- linux-2.6.37/drivers/net/wireless/Makefile 2011-01-04 17:50:19.000000000 -0700 ++++ linux-2.6.37-new/drivers/net/wireless/Makefile 2011-01-08 06:01:04.034836160 -0700 +@@ -36,6 +36,8 @@ obj-$(CONFIG_LIBERTAS) += libertas/ + + obj-$(CONFIG_LIBERTAS_THINFIRM) += libertas_tf/ + ++obj-$(CONFIG_LIBERTAS_UAP) += libertas_uap/ ++ + obj-$(CONFIG_ADM8211) += adm8211.o + + obj-$(CONFIG_MWL8K) += mwl8k.o +diff -Naupr linux-2.6.37/drivers/net/wireless/libertas_uap/Makefile linux-2.6.37-new/drivers/net/wireless/libertas_uap/Makefile +--- linux-2.6.37/drivers/net/wireless/libertas_uap/Makefile 1969-12-31 17:00:00.000000000 -0700 ++++ linux-2.6.37-new/drivers/net/wireless/libertas_uap/Makefile 2011-01-08 06:01:04.036836021 -0700 +@@ -0,0 +1,6 @@ ++obj-$(CONFIG_LIBERTAS_UAP) += uap8xxx.o ++ ++uap8xxx-y += uap_main.o uap_sdio_mmc.o ++uap8xxx-$(CONFIG_PROC_FS) += uap_proc.o uap_debug.o ++ ++EXTRA_CFLAGS += -DFPNUM='"52"' -DPXA3XX_DMA_ALIGN -DDEBUG_LEVEL1 +diff -Naupr linux-2.6.37/drivers/net/wireless/libertas_uap/uap_debug.c linux-2.6.37-new/drivers/net/wireless/libertas_uap/uap_debug.c +--- linux-2.6.37/drivers/net/wireless/libertas_uap/uap_debug.c 1969-12-31 17:00:00.000000000 -0700 ++++ linux-2.6.37-new/drivers/net/wireless/libertas_uap/uap_debug.c 2011-01-08 06:01:04.038835884 -0700 +@@ -0,0 +1,261 @@ ++/** @file uap_debug.c ++ * @brief This file contains functions for debug proc file. ++ * ++ * Copyright (C) 2008-2009, Marvell International Ltd. ++ * ++ * This software file (the "File") is distributed by Marvell International ++ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 ++ * (the "License"). You may use, redistribute and/or modify this File in ++ * accordance with the terms and conditions of the License, a copy of which ++ * is available along with the File in the gpl.txt file or by writing to ++ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. ++ * ++ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ++ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about ++ * this warranty disclaimer. ++ * ++ */ ++#ifdef CONFIG_PROC_FS ++#include "uap_headers.h" ++ ++/******************************************************** ++ Local Variables ++********************************************************/ ++ ++#define item_size(n) (sizeof ((uap_adapter *)0)->n) ++#define item_addr(n) ((u32) &((uap_adapter *)0)->n) ++ ++#define item_dbg_size(n) (sizeof (((uap_adapter *)0)->dbg.n)) ++#define item_dbg_addr(n) ((u32) &(((uap_adapter *)0)->dbg.n)) ++ ++#define item_dev_size(n) (sizeof ((uap_dev_t *)0)->n) ++#define item_dev_addr(n) ((u32) &((uap_dev_t *)0)->n) ++ ++/** MicroAp device offset */ ++#define OFFSET_UAP_DEV 0x01 ++/** Bluetooth adapter offset */ ++#define OFFSET_UAP_ADAPTER 0x02 ++ ++struct debug_data ++{ ++ /** Name */ ++ char name[32]; ++ /** Size */ ++ u32 size; ++ /** Address */ ++ u32 addr; ++ /** Offset */ ++ u32 offset; ++ /** Flag */ ++ u32 flag; ++}; ++ ++/* To debug any member of uap_adapter, simply add one line here. ++ */ ++static struct debug_data items[] = { ++ {"cmd_sent", item_dev_size(cmd_sent), 0, item_dev_addr(cmd_sent), ++ OFFSET_UAP_DEV}, ++ {"data_sent", item_dev_size(data_sent), 0, item_dev_addr(data_sent), ++ OFFSET_UAP_DEV}, ++ {"IntCounter", item_size(IntCounter), 0, item_addr(IntCounter), ++ OFFSET_UAP_ADAPTER}, ++ {"cmd_pending", item_size(cmd_pending), 0, item_addr(cmd_pending), ++ OFFSET_UAP_ADAPTER}, ++ {"num_cmd_h2c_fail", item_dbg_size(num_cmd_host_to_card_failure), 0, ++ item_dbg_addr(num_cmd_host_to_card_failure), OFFSET_UAP_ADAPTER}, ++ {"num_tx_h2c_fail", item_dbg_size(num_tx_host_to_card_failure), 0, ++ item_dbg_addr(num_tx_host_to_card_failure), OFFSET_UAP_ADAPTER}, ++ {"psmode", item_size(psmode), 0, item_addr(psmode), OFFSET_UAP_ADAPTER}, ++ {"ps_state", item_size(ps_state), 0, item_addr(ps_state), ++ OFFSET_UAP_ADAPTER}, ++#ifdef DEBUG_LEVEL1 ++ {"drvdbg", sizeof(drvdbg), (u32) & drvdbg, 0, 0} ++#endif ++}; ++ ++static int num_of_items = sizeof(items) / sizeof(items[0]); ++ ++/******************************************************** ++ Global Variables ++********************************************************/ ++ ++/******************************************************** ++ Local Functions ++********************************************************/ ++/** ++ * @brief proc read function ++ * ++ * @param page pointer to buffer ++ * @param s read data starting position ++ * @param off offset ++ * @param cnt counter ++ * @param eof end of file flag ++ * @param data data to output ++ * @return number of output data ++ */ ++static int ++uap_debug_read(char *page, char **s, off_t off, int cnt, int *eof, void *data) ++{ ++ int val = 0; ++ char *p = page; ++ int i; ++ ++ struct debug_data *d = (struct debug_data *) data; ++ ++ if (MODULE_GET == 0) ++ return UAP_STATUS_FAILURE; ++ ++ for (i = 0; i < num_of_items; i++) { ++ if (d[i].size == 1) ++ val = *((u8 *) d[i].addr); ++ else if (d[i].size == 2) ++ val = *((u16 *) d[i].addr); ++ else if (d[i].size == 4) ++ val = *((u32 *) d[i].addr); ++ ++ p += sprintf(p, "%s=%d\n", d[i].name, val); ++ } ++ MODULE_PUT; ++ return p - page; ++} ++ ++/** ++ * @brief proc write function ++ * ++ * @param f file pointer ++ * @param buf pointer to data buffer ++ * @param cnt data number to write ++ * @param data data to write ++ * @return number of data ++ */ ++static int ++uap_debug_write(struct file *f, const char *buf, unsigned long cnt, void *data) ++{ ++ int r, i; ++ char *pdata; ++ char *p; ++ char *p0; ++ char *p1; ++ char *p2; ++ struct debug_data *d = (struct debug_data *) data; ++ ++ if (MODULE_GET == 0) ++ return UAP_STATUS_FAILURE; ++ ++ pdata = (char *) kmalloc(cnt, GFP_KERNEL); ++ if (pdata == NULL) { ++ MODULE_PUT; ++ return 0; ++ } ++ ++ if (copy_from_user(pdata, buf, cnt)) { ++ PRINTM(INFO, "Copy from user failed\n"); ++ kfree(pdata); ++ MODULE_PUT; ++ return 0; ++ } ++ ++ p0 = pdata; ++ for (i = 0; i < num_of_items; i++) { ++ do { ++ p = strstr(p0, d[i].name); ++ if (p == NULL) ++ break; ++ p1 = strchr(p, '\n'); ++ if (p1 == NULL) ++ break; ++ p0 = p1++; ++ p2 = strchr(p, '='); ++ if (!p2) ++ break; ++ p2++; ++ r = string_to_number(p2); ++ if (d[i].size == 1) ++ *((u8 *) d[i].addr) = (u8) r; ++ else if (d[i].size == 2) ++ *((u16 *) d[i].addr) = (u16) r; ++ else if (d[i].size == 4) ++ *((u32 *) d[i].addr) = (u32) r; ++ break; ++ } while (TRUE); ++ } ++ kfree(pdata); ++#ifdef DEBUG_LEVEL1 ++ printk(KERN_ALERT "drvdbg = 0x%x\n", drvdbg); ++ printk(KERN_ALERT "INFO (%08lx) %s\n", DBG_INFO, ++ (drvdbg & DBG_INFO) ? "X" : ""); ++ printk(KERN_ALERT "WARN (%08lx) %s\n", DBG_WARN, ++ (drvdbg & DBG_WARN) ? "X" : ""); ++ printk(KERN_ALERT "ENTRY (%08lx) %s\n", DBG_ENTRY, ++ (drvdbg & DBG_ENTRY) ? "X" : ""); ++ printk(KERN_ALERT "CMD_D (%08lx) %s\n", DBG_CMD_D, ++ (drvdbg & DBG_CMD_D) ? "X" : ""); ++ printk(KERN_ALERT "DAT_D (%08lx) %s\n", DBG_DAT_D, ++ (drvdbg & DBG_DAT_D) ? "X" : ""); ++ printk(KERN_ALERT "CMND (%08lx) %s\n", DBG_CMND, ++ (drvdbg & DBG_CMND) ? "X" : ""); ++ printk(KERN_ALERT "DATA (%08lx) %s\n", DBG_DATA, ++ (drvdbg & DBG_DATA) ? "X" : ""); ++ printk(KERN_ALERT "ERROR (%08lx) %s\n", DBG_ERROR, ++ (drvdbg & DBG_ERROR) ? "X" : ""); ++ printk(KERN_ALERT "FATAL (%08lx) %s\n", DBG_FATAL, ++ (drvdbg & DBG_FATAL) ? "X" : ""); ++ printk(KERN_ALERT "MSG (%08lx) %s\n", DBG_MSG, ++ (drvdbg & DBG_MSG) ? "X" : ""); ++#endif ++ MODULE_PUT; ++ return cnt; ++} ++ ++/******************************************************** ++ Global Functions ++********************************************************/ ++/** ++ * @brief create debug proc file ++ * ++ * @param priv pointer uap_private ++ * @param dev pointer net_device ++ * @return N/A ++ */ ++void ++uap_debug_entry(uap_private * priv, struct net_device *dev) ++{ ++ int i; ++ struct proc_dir_entry *r; ++ ++ if (priv->proc_entry == NULL) ++ return; ++ ++ for (i = 0; i < num_of_items; i++) { ++ if (items[i].flag & OFFSET_UAP_ADAPTER) ++ items[i].addr = items[i].offset + (u32) priv->adapter; ++ if (items[i].flag & OFFSET_UAP_DEV) ++ items[i].addr = items[i].offset + (u32) & priv->uap_dev; ++ } ++ r = create_proc_entry("debug", 0644, priv->proc_entry); ++ if (r == NULL) ++ return; ++ ++ r->data = &items[0]; ++ r->read_proc = uap_debug_read; ++ r->write_proc = uap_debug_write; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) ++ r->owner = THIS_MODULE; ++#endif ++} ++ ++/** ++ * @brief remove proc file ++ * ++ * @param priv pointer uap_private ++ * @return N/A ++ */ ++void ++uap_debug_remove(uap_private * priv) ++{ ++ remove_proc_entry("debug", priv->proc_entry); ++} ++ ++#endif +diff -Naupr linux-2.6.37/drivers/net/wireless/libertas_uap/uap_drv.h linux-2.6.37-new/drivers/net/wireless/libertas_uap/uap_drv.h +--- linux-2.6.37/drivers/net/wireless/libertas_uap/uap_drv.h 1969-12-31 17:00:00.000000000 -0700 ++++ linux-2.6.37-new/drivers/net/wireless/libertas_uap/uap_drv.h 2011-06-26 00:15:04.040835746 -0700 +@@ -0,0 +1,667 @@ ++/** @file uap_drv.h ++ * @brief This file contains Linux OS related definitions and ++ * declarations, uAP driver ++ * ++ * Copyright (C) 2008-2009, Marvell International Ltd. ++ * ++ * This software file (the "File") is distributed by Marvell International ++ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 ++ * (the "License"). You may use, redistribute and/or modify this File in ++ * accordance with the terms and conditions of the License, a copy of which ++ * is available along with the File in the gpl.txt file or by writing to ++ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. ++ * ++ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ++ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about ++ * this warranty disclaimer. ++ * ++ */ ++ ++#ifndef _UAP_DRV_H ++#define _UAP_DRV_H ++ ++/** Driver release version */ ++#define DRIVER_VERSION "26146" ++ ++/** True */ ++#ifndef TRUE ++#define TRUE 1 ++#endif ++/** False */ ++#ifndef FALSE ++#define FALSE 0 ++#endif ++ ++/** Bit definitions */ ++#ifndef BIT ++#define BIT(x) (1UL << (x)) ++#endif ++ ++/** Dma addresses are 32-bits wide. */ ++#ifndef __ATTRIB_ALIGN__ ++#define __ATTRIB_ALIGN__ __attribute__((aligned(4))) ++#endif ++ ++/** attribute pack */ ++#ifndef __ATTRIB_PACK__ ++#define __ATTRIB_PACK__ __attribute__ ((packed)) ++#endif ++ ++/** Debug Macro definition*/ ++#ifdef DEBUG_LEVEL1 ++ ++extern u32 drvdbg; ++ ++/** Debug message control bit definition for drvdbg */ ++/** Debug message */ ++#define DBG_MSG BIT(0) ++/** Debug fatal message */ ++#define DBG_FATAL BIT(1) ++/** Debug error message */ ++#define DBG_ERROR BIT(2) ++/** Debug data message */ ++#define DBG_DATA BIT(3) ++/** Debug command message */ ++#define DBG_CMND BIT(4) ++ ++/** Debug data */ ++#define DBG_DAT_D BIT(16) ++/** Debug command */ ++#define DBG_CMD_D BIT(17) ++ ++/** Debug entry */ ++#define DBG_ENTRY BIT(28) ++/** Debug warning */ ++#define DBG_WARN BIT(29) ++/** Debug info */ ++#define DBG_INFO BIT(30) ++ ++/** Print info */ ++#define PRINTM_INFO(msg...) {if (drvdbg & DBG_INFO) printk(KERN_DEBUG msg);} ++/** Print warn message */ ++#define PRINTM_WARN(msg...) {if (drvdbg & DBG_WARN) printk(KERN_DEBUG msg);} ++/** Print entry */ ++#define PRINTM_ENTRY(msg...) {if (drvdbg & DBG_ENTRY) printk(KERN_DEBUG msg);} ++/** Print cmd_d */ ++#define PRINTM_CMD_D(msg...) {if (drvdbg & DBG_CMD_D) printk(KERN_DEBUG msg);} ++/** Print data_d */ ++#define PRINTM_DAT_D(msg...) {if (drvdbg & DBG_DAT_D) printk(KERN_DEBUG msg);} ++/** Print command */ ++#define PRINTM_CMND(msg...) {if (drvdbg & DBG_CMND) printk(KERN_DEBUG msg);} ++/** Print data */ ++#define PRINTM_DATA(msg...) {if (drvdbg & DBG_DATA) printk(KERN_DEBUG msg);} ++/** Print error message */ ++#define PRINTM_ERROR(msg...) {if (drvdbg & DBG_ERROR) printk(KERN_DEBUG msg);} ++/** Print fatal message */ ++#define PRINTM_FATAL(msg...) {if (drvdbg & DBG_FATAL) printk(KERN_DEBUG msg);} ++/** Print message */ ++#define PRINTM_MSG(msg...) {if (drvdbg & DBG_MSG) printk(KERN_ALERT msg);} ++/** Print level */ ++#define PRINTM(level,msg...) PRINTM_##level(msg) ++ ++#else ++ ++#define PRINTM(level,msg...) do {} while (0) ++ ++#endif /* DEBUG_LEVEL1 */ ++ ++/** Wait until a condition becomes true */ ++#define ASSERT(cond) \ ++do { \ ++ if (!(cond)) \ ++ PRINTM(INFO, "ASSERT: %s, %s:%i\n", \ ++ __FUNCTION__, __FILE__, __LINE__); \ ++} while(0) ++ ++/** Log enrty point for debugging */ ++#define ENTER() PRINTM(ENTRY, "Enter: %s, %s:%i\n", __FUNCTION__, \ ++ __FILE__, __LINE__) ++/** Log exit point for debugging */ ++#define LEAVE() PRINTM(ENTRY, "Leave: %s, %s:%i\n", __FUNCTION__, \ ++ __FILE__, __LINE__) ++ ++#ifdef DEBUG_LEVEL1 ++/** Dump buffer length */ ++#define DBG_DUMP_BUF_LEN 64 ++/** Maximum dump per line */ ++#define MAX_DUMP_PER_LINE 16 ++/** Data dump length */ ++#define DATA_DUMP_LEN 32 ++ ++static inline void ++hexdump(char *prompt, u8 * buf, int len) ++{ ++ int i; ++ char dbgdumpbuf[DBG_DUMP_BUF_LEN]; ++ char *ptr = dbgdumpbuf; ++ ++ printk(KERN_DEBUG "%s:\n", prompt); ++ for (i = 1; i <= len; i++) { ++ ptr += sprintf(ptr, "%02x ", *buf); ++ buf++; ++ if (i % MAX_DUMP_PER_LINE == 0) { ++ *ptr = 0; ++ printk(KERN_DEBUG "%s\n", dbgdumpbuf); ++ ptr = dbgdumpbuf; ++ } ++ } ++ if (len % MAX_DUMP_PER_LINE) { ++ *ptr = 0; ++ printk(KERN_DEBUG "%s\n", dbgdumpbuf); ++ } ++} ++ ++/** Debug command */ ++#define DBG_HEXDUMP_CMD_D(x,y,z) {if (drvdbg & DBG_CMD_D) hexdump(x,y,z);} ++/** Debug data */ ++#define DBG_HEXDUMP_DAT_D(x,y,z) {if (drvdbg & DBG_DAT_D) hexdump(x,y,z);} ++/** Debug hexdump */ ++#define DBG_HEXDUMP(level,x,y,z) DBG_HEXDUMP_##level(x,y,z) ++/** hexdump */ ++#define HEXDUMP(x,y,z) {if (drvdbg & DBG_INFO) hexdump(x,y,z);} ++#else ++/** Do nothing since debugging is not turned on */ ++#define DBG_HEXDUMP(level,x,y,z) do {} while (0) ++/** Do nothing since debugging is not turned on */ ++#define HEXDUMP(x,y,z) do {} while (0) ++#endif ++ ++/** ++ * Typedefs ++ */ ++/** Unsigned char */ ++typedef u8 BOOLEAN; ++ ++/* ++ * OS macro definitions ++ */ ++/** OS macro to get time */ ++#define os_time_get() jiffies ++ ++/** OS macro to update transfer start time */ ++#define UpdateTransStart(dev) { \ ++ dev->trans_start = jiffies; \ ++} ++ ++/** Try to get a reference to the module */ ++#define MODULE_GET try_module_get(THIS_MODULE) ++/** Decrease module reference count */ ++#define MODULE_PUT module_put(THIS_MODULE) ++ ++/** OS macro to initialize semaphore */ ++#define OS_INIT_SEMAPHORE(x) sema_init(x,1) ++/** OS macro to acquire blocking semaphore */ ++#define OS_ACQ_SEMAPHORE_BLOCK(x) down_interruptible(x) ++/** OS macro to acquire non-blocking semaphore */ ++#define OS_ACQ_SEMAPHORE_NOBLOCK(x) down_trylock(x) ++/** OS macro to release semaphore */ ++#define OS_REL_SEMAPHORE(x) up(x) ++ ++static inline void ++os_sched_timeout(u32 millisec) ++{ ++ set_current_state(TASK_INTERRUPTIBLE); ++ schedule_timeout((millisec * HZ) / 1000); ++} ++ ++/** Maximum size of ethernet packet */ ++#define MRVDRV_MAXIMUM_ETH_PACKET_SIZE 1514 ++ ++/** Maximum size of multicast list */ ++#define MRVDRV_MAX_MULTICAST_LIST_SIZE 32 ++ ++/** Find minimum */ ++#ifndef MIN ++#define MIN(a,b) ((a) < (b) ? (a) : (b)) ++#endif ++ ++/** Find maximum */ ++#ifndef MAX ++#define MAX(a,b) ((a) > (b) ? (a) : (b)) ++#endif ++ ++/** Find number of elements */ ++#ifndef NELEMENTS ++#define NELEMENTS(x) (sizeof(x)/sizeof(x[0])) ++#endif ++ ++/** Buffer Constants */ ++ ++/** Size of command buffer */ ++#define MRVDRV_SIZE_OF_CMD_BUFFER (2 * 1024) ++ ++/** Length of device length */ ++#define DEV_NAME_LEN 32 ++ ++/** Length of ethernet address */ ++#ifndef ETH_ALEN ++#define ETH_ALEN 6 ++#endif ++ ++/** Default watchdog timeout */ ++#define MRVDRV_DEFAULT_WATCHDOG_TIMEOUT (2 * HZ) ++ ++/** Success */ ++#define UAP_STATUS_SUCCESS (0) ++/** Failure */ ++#define UAP_STATUS_FAILURE (-1) ++/** Not accepted */ ++#define UAP_STATUS_NOT_ACCEPTED (-2) ++ ++/** Max loop count (* 100ms) for waiting device ready at init time */ ++#define MAX_WAIT_DEVICE_READY_COUNT 50 ++ ++/** Tx high watermark. Stop Tx queue after this is crossed */ ++#define TX_HIGH_WATERMARK 4 ++/** Tx low watermark. Restart Tx queue after this is crossed */ ++#define TX_LOW_WATERMARK 2 ++ ++/** Netlink protocol number */ ++#define NETLINK_MARVELL (MAX_LINKS - 1) ++/** Netlink maximum payload size */ ++#define NL_MAX_PAYLOAD 1024 ++/** Netlink multicast group number */ ++#define NL_MULTICAST_GROUP 1 ++ ++/** 20 seconds */ ++#define MRVDRV_TIMER_20S 20000 ++ ++/** Host Command option for wait till Send */ ++#define HostCmd_OPTION_WAITFORSEND 0x0001 ++/** Host Command option for wait for RSP */ ++#define HostCmd_OPTION_WAITFORRSP 0x0002 ++/** Host Command option for wait for RSP or Timeout */ ++#define HostCmd_OPTION_WAITFORRSP_TIMEOUT 0x0003 ++/** Host Command option for wait for RSP of sleep confirm */ ++#define HostCmd_OPTION_WAITFORRSP_SLEEPCONFIRM 0x0004 ++ ++/** Sleep until a condition gets true or a timeout elapses */ ++#define os_wait_interruptible_timeout(waitq, cond, timeout) \ ++ wait_event_interruptible_timeout(waitq, cond, ((timeout) * HZ / 1000)) ++ ++/** Private command ID to Host command */ ++#define UAPHOSTCMD (SIOCDEVPRIVATE + 1) ++ ++/** Private command ID to Power Mode */ ++#define UAP_POWER_MODE (SIOCDEVPRIVATE + 3) ++/** sleep_param */ ++typedef struct _ps_sleep_param ++{ ++ /** control bitmap */ ++ u32 ctrl_bitmap; ++ /** minimum sleep period (micro second) */ ++ u32 min_sleep; ++ /** maximum sleep period (micro second) */ ++ u32 max_sleep; ++} ps_sleep_param; ++ ++/** inactivity sleep_param */ ++typedef struct _inact_sleep_param ++{ ++ /** inactivity timeout (micro second) */ ++ u32 inactivity_to; ++ /** miniumu awake period (micro second) */ ++ u32 min_awake; ++ /** maximum awake period (micro second) */ ++ u32 max_awake; ++} inact_sleep_param; ++ ++/** flag for ps mode */ ++#define PS_FLAG_PS_MODE 1 ++/** flag for sleep param */ ++#define PS_FLAG_SLEEP_PARAM 2 ++/** flag for inactivity sleep param */ ++#define PS_FLAG_INACT_SLEEP_PARAM 4 ++ ++/** Disable power mode */ ++#define PS_MODE_DISABLE 0 ++/** Enable periodic dtim ps */ ++#define PS_MODE_PERIODIC_DTIM 1 ++/** Enable inactivity ps */ ++#define PS_MODE_INACTIVITY 2 ++ ++/** sleep parameter */ ++#define SLEEP_PARAMETER 1 ++/** inactivity sleep parameter */ ++#define INACTIVITY_SLEEP_PARAMETER 2 ++/** ps_mgmt */ ++typedef struct _ps_mgmt ++{ ++ /** flags for valid field */ ++ u16 flags; ++ /** power mode */ ++ u16 ps_mode; ++ /** sleep param */ ++ ps_sleep_param sleep_param; ++ /** inactivity sleep param */ ++ inact_sleep_param inact_param; ++} ps_mgmt; ++ ++/** Semaphore structure */ ++typedef struct semaphore SEMAPHORE; ++ ++/** Global Varibale Declaration */ ++/** Private data structure of the device */ ++typedef struct _uap_private uap_private; ++/** Adapter data structure of the device */ ++typedef struct _uap_adapter uap_adapter; ++/** private structure */ ++extern uap_private *uappriv; ++ ++/** ENUM definition*/ ++ ++/** Hardware status codes */ ++typedef enum _HARDWARE_STATUS ++{ ++ HWReady, ++ HWInitializing, ++ HWReset, ++ HWClosing, ++ HWNotReady ++} HARDWARE_STATUS; ++ ++/** info for debug purpose */ ++typedef struct _uap_dbg ++{ ++ /** Number of host to card command failures */ ++ u32 num_cmd_host_to_card_failure; ++ /** Number of host to card Tx failures */ ++ u32 num_tx_host_to_card_failure; ++} uap_dbg; ++ ++/** Set thread state */ ++#define OS_SET_THREAD_STATE(x) set_current_state(x) ++ ++typedef struct ++{ ++ /** Task */ ++ struct task_struct *task; ++ /** Queue */ ++ wait_queue_head_t waitQ; ++ /** PID */ ++ pid_t pid; ++ /** Private structure */ ++ void *priv; ++} uap_thread; ++ ++static inline void ++uap_activate_thread(uap_thread * thr) ++{ ++ /** Record the thread pid */ ++ thr->pid = current->pid; ++ ++ /** Initialize the wait queue */ ++ init_waitqueue_head(&thr->waitQ); ++} ++ ++static inline void ++uap_deactivate_thread(uap_thread * thr) ++{ ++ thr->pid = 0; ++ return; ++} ++ ++static inline void ++uap_create_thread(int (*uapfunc) (void *), uap_thread * thr, char *name) ++{ ++ thr->task = kthread_run(uapfunc, thr, "%s", name); ++} ++ ++static inline int ++uap_terminate_thread(uap_thread * thr) ++{ ++ /* Check if the thread is active or not */ ++ if (!thr->pid) ++ return -1; ++ kthread_stop(thr->task); ++ return 0; ++} ++ ++/** Data structure for the Marvell uAP device */ ++typedef struct _uap_dev ++{ ++ /** device name */ ++ char name[DEV_NAME_LEN]; ++ /** card pointer */ ++ void *card; ++ /** IO port */ ++ u32 ioport; ++ /** Rx unit */ ++ u8 rx_unit; ++ /** Data sent: ++ TRUE - Data is sent to fw, no Tx Done received ++ FALSE - Tx done received for previous Tx */ ++ BOOLEAN data_sent; ++ /** CMD sent: ++ TRUE - CMD is sent to fw, no CMD Done received ++ FALSE - CMD done received for previous CMD */ ++ BOOLEAN cmd_sent; ++ /** netdev pointer */ ++ struct net_device *netdev; ++} uap_dev_t, *puap_dev_t; ++ ++/** Private structure for the MV device */ ++struct _uap_private ++{ ++ /** Device open */ ++ int open; ++ ++ /** Device adapter structure */ ++ uap_adapter *adapter; ++ /** Device structure */ ++ uap_dev_t uap_dev; ++ ++ /** Net device statistics structure */ ++ struct net_device_stats stats; ++ ++ /** Number of Tx timeouts */ ++ u32 num_tx_timeout; ++ ++ /** Media connection status */ ++ BOOLEAN MediaConnected; ++ ++#ifdef CONFIG_PROC_FS ++ struct proc_dir_entry *proc_uap; ++ struct proc_dir_entry *proc_entry; ++#endif /* CONFIG_PROC_FS */ ++ ++ /** Firmware helper */ ++ const struct firmware *fw_helper; ++ /** Firmware */ ++ const struct firmware *firmware; ++ /** Hotplug device */ ++ struct device *hotplug_device; ++ /** thread to service interrupts */ ++ uap_thread MainThread; ++ /** Driver lock */ ++ spinlock_t driver_lock; ++ /** Driver lock flags */ ++ ulong driver_flags; ++ ++}; ++ ++/** PS_CMD_ConfirmSleep */ ++typedef struct _PS_CMD_ConfirmSleep ++{ ++ /** SDIO Length */ ++ u16 SDLen; ++ /** SDIO Type */ ++ u16 SDType; ++ /** Command */ ++ u16 Command; ++ /** Size */ ++ u16 Size; ++ /** Sequence number */ ++ u16 SeqNum; ++ /** Result */ ++ u16 Result; ++} __ATTRIB_PACK__ PS_CMD_ConfirmSleep, *PPS_CMD_ConfirmSleep; ++ ++/** Wlan Adapter data structure*/ ++struct _uap_adapter ++{ ++ /** Power save confirm sleep command */ ++ PS_CMD_ConfirmSleep PSConfirmSleep; ++ /** Device status */ ++ HARDWARE_STATUS HardwareStatus; ++ /** Interrupt counter */ ++ u32 IntCounter; ++ /** Tx packet queue */ ++ struct sk_buff_head tx_queue; ++ /** Cmd packet queue */ ++ struct sk_buff_head cmd_queue; ++ /** Command sequence number */ ++ u16 SeqNum; ++ /** Command buffer */ ++ u8 *CmdBuf; ++ /** cmd pending flag */ ++ u8 cmd_pending; ++ /** cmd wait option */ ++ u8 cmd_wait_option; ++ /** Command buffer length */ ++ u32 CmdSize; ++ /** Command wait queue */ ++ wait_queue_head_t cmdwait_q __ATTRIB_ALIGN__; ++ /** Command wait queue state flag */ ++ u8 CmdWaitQWoken; ++ /** PnP support */ ++ BOOLEAN SurpriseRemoved; ++ /** Debug */ ++ uap_dbg dbg; ++ /** Netlink kernel socket */ ++ struct sock *nl_sk; ++ /** Semaphore for CMD */ ++ SEMAPHORE CmdSem; ++ /** Power Save mode */ ++ u8 psmode; ++ /** Power Save state */ ++ u8 ps_state; ++ /** Number of wakeup tries */ ++ u32 WakeupTries; ++}; ++ ++static inline int ++os_upload_rx_packet(uap_private * priv, struct sk_buff *skb) ++{ ++ skb->dev = priv->uap_dev.netdev; ++ skb->protocol = eth_type_trans(skb, priv->uap_dev.netdev); ++ skb->ip_summed = CHECKSUM_UNNECESSARY; ++ if (in_interrupt()) ++ netif_rx(skb); ++ else ++ netif_rx_ni(skb); ++ return 0; ++} ++ ++/* ++ * netif carrier_on/off and start(wake)/stop_queue handling ++ */ ++static inline void ++os_carrier_on(uap_private * priv) ++{ ++ if (!netif_carrier_ok(priv->uap_dev.netdev) && ++ (priv->MediaConnected == TRUE)) { ++ netif_carrier_on(priv->uap_dev.netdev); ++ } ++} ++ ++static inline void ++os_carrier_off(uap_private * priv) ++{ ++ if (netif_carrier_ok(priv->uap_dev.netdev)) { ++ netif_carrier_off(priv->uap_dev.netdev); ++ } ++} ++ ++static inline void ++os_start_queue(uap_private * priv) ++{ ++ if (netif_queue_stopped(priv->uap_dev.netdev) && ++ (priv->MediaConnected == TRUE)) { ++ netif_wake_queue(priv->uap_dev.netdev); ++ } ++} ++ ++static inline void ++os_stop_queue(uap_private * priv) ++{ ++ if (!netif_queue_stopped(priv->uap_dev.netdev)) { ++ netif_stop_queue(priv->uap_dev.netdev); ++ } ++} ++ ++/** Interface specific header */ ++#define INTF_HEADER_LEN 4 ++ ++/** headroom alignment for tx packet */ ++#define HEADER_ALIGNMENT 8 ++ ++/** The number of times to try when polling for status bits */ ++#define MAX_POLL_TRIES 100 ++ ++/** Length of SNAP header */ ++#define MRVDRV_SNAP_HEADER_LEN 8 ++ ++/** Extra length of Tx packet buffer */ ++#define EXTRA_LEN 36 ++ ++/** Buffer size for ethernet Tx packets */ ++#define MRVDRV_ETH_TX_PACKET_BUFFER_SIZE \ ++ (ETH_FRAME_LEN + sizeof(TxPD) + EXTRA_LEN) ++ ++/** Buffer size for ethernet Rx packets */ ++#define MRVDRV_ETH_RX_PACKET_BUFFER_SIZE \ ++ (ETH_FRAME_LEN + sizeof(RxPD) \ ++ + MRVDRV_SNAP_HEADER_LEN + EXTRA_LEN) ++ ++/** Packet type: data, command & event */ ++typedef enum _mv_type ++{ ++ MV_TYPE_DAT = 0, ++ MV_TYPE_CMD = 1, ++ MV_TYPE_EVENT = 3 ++} mv_type; ++ ++/** Disable interrupt */ ++#define OS_INT_DISABLE spin_lock_irqsave(&priv->driver_lock, priv->driver_flags) ++/** Enable interrupt */ ++#define OS_INT_RESTORE spin_unlock_irqrestore(&priv->driver_lock, priv->driver_flags) ++ ++int uap_process_rx_packet(uap_private * priv, struct sk_buff *skb); ++void uap_interrupt(uap_private * priv); ++uap_private *uap_add_card(void *card); ++int uap_remove_card(void *card); ++int uap_process_event(uap_private * priv, u8 * payload, uint len); ++int uap_soft_reset(uap_private * priv); ++int uap_process_sleep_confirm_resp(uap_private * priv, u8 * resp, int resp_len); ++ ++#ifdef CONFIG_PROC_FS ++/** The proc fs interface */ ++void uap_proc_entry(uap_private * priv, struct net_device *dev); ++void uap_proc_remove(uap_private * priv); ++int string_to_number(char *s); ++void uap_debug_entry(uap_private * priv, struct net_device *dev); ++void uap_debug_remove(uap_private * priv); ++#endif /* CONFIG_PROC_FS */ ++ ++int sbi_register(void); ++ ++void sbi_unregister(void); ++int sbi_register_dev(uap_private * priv); ++int sbi_unregister_dev(uap_private * priv); ++int sbi_prog_fw_w_helper(uap_private *); ++ ++int sbi_host_to_card(uap_private * priv, u8 * payload, u16 nb); ++int sbi_enable_host_int(uap_private * priv); ++int sbi_disable_host_int(uap_private * priv); ++ ++int sbi_get_int_status(uap_private * priv, u8 * ireg); ++/** Check firmware status */ ++int sbi_check_fw_status(uap_private *, int); ++int sbi_prog_helper(uap_private *); ++ ++int sbi_wakeup_firmware(uap_private * priv); ++ ++#endif /* _UAP_DRV_H */ +diff -Naupr linux-2.6.37/drivers/net/wireless/libertas_uap/uap_fw.h linux-2.6.37-new/drivers/net/wireless/libertas_uap/uap_fw.h +--- linux-2.6.37/drivers/net/wireless/libertas_uap/uap_fw.h 1969-12-31 17:00:00.000000000 -0700 ++++ linux-2.6.37-new/drivers/net/wireless/libertas_uap/uap_fw.h 2011-01-08 06:01:04.042835607 -0700 +@@ -0,0 +1,359 @@ ++/** @file uap_fw.h ++ * ++ * @brief This file contains firmware specific defines. ++ * ++ * Copyright (C) 2008-2009, Marvell International Ltd. ++ * ++ * This software file (the "File") is distributed by Marvell International ++ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 ++ * (the "License"). You may use, redistribute and/or modify this File in ++ * accordance with the terms and conditions of the License, a copy of which ++ * is available along with the File in the gpl.txt file or by writing to ++ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. ++ * ++ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ++ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about ++ * this warranty disclaimer. ++ * ++ */ ++/******************************************************** ++Change log: ++ 02/26/08: Initial creation ++********************************************************/ ++ ++#ifndef _UAP_FW_H ++#define _UAP_FW_H ++ ++/** uap upload size */ ++#define UAP_UPLD_SIZE 2312 ++/** Packet type Micro AP */ ++#define PKT_TYPE_MICROAP 1 ++/** Packet type client */ ++#define PKT_TYPE_CLIENT 0 ++ ++/** TxPD descriptor */ ++typedef struct _TxPD ++{ ++ /** Bss Type */ ++ u8 BssType; ++ /** Bss num */ ++ u8 BssNum; ++ /** Tx packet length */ ++ u16 TxPktLength; ++ /** Tx packet offset */ ++ u16 TxPktOffset; ++ /** Tx packet type */ ++ u16 TxPktType; ++ /** Tx Control */ ++ u32 TxControl; ++ /** reserved */ ++ u32 reserved[2]; ++} __ATTRIB_PACK__ TxPD, *PTxPD; ++ ++/** RxPD Descriptor */ ++typedef struct _RxPD ++{ ++ /** Bss Type */ ++ u8 BssType; ++ /** Bss Num */ ++ u8 BssNum; ++ /** Tx packet length */ ++ u16 RxPktLength; ++ /** Tx packet offset */ ++ u16 RxPktOffset; ++} __ATTRIB_PACK__ RxPD, *PRxPD; ++ ++#ifdef BIG_ENDIAN ++/** Convert from 16 bit little endian format to CPU format */ ++#define uap_le16_to_cpu(x) le16_to_cpu(x) ++/** Convert from 32 bit little endian format to CPU format */ ++#define uap_le32_to_cpu(x) le32_to_cpu(x) ++/** Convert from 64 bit little endian format to CPU format */ ++#define uap_le64_to_cpu(x) le64_to_cpu(x) ++/** Convert to 16 bit little endian format from CPU format */ ++#define uap_cpu_to_le16(x) cpu_to_le16(x) ++/** Convert to 32 bit little endian format from CPU format */ ++#define uap_cpu_to_le32(x) cpu_to_le32(x) ++/** Convert to 64 bit little endian format from CPU format */ ++#define uap_cpu_to_le64(x) cpu_to_le64(x) ++ ++/** Convert TxPD to little endian format from CPU format */ ++#define endian_convert_TxPD(x); \ ++ { \ ++ (x)->TxPktLength = uap_cpu_to_le16((x)->TxPktLength); \ ++ (x)->TxPktOffset = uap_cpu_to_le32((x)->TxPktOffset); \ ++ (x)->TxControl = uap_cpu_to_le32((x)->TxControl); \ ++ (x)->TxPktType = uap_cpu_to_le32((x)->TxPktType); \ ++ } ++ ++/** Convert RxPD from little endian format to CPU format */ ++#define endian_convert_RxPD(x); \ ++ { \ ++ (x)->RxPktLength = uap_le16_to_cpu((x)->RxPktLength); \ ++ (x)->RxPktOffset = uap_le32_to_cpu((x)->RxPktOffset); \ ++ } ++#else /* BIG_ENDIAN */ ++/** Do nothing */ ++#define uap_le16_to_cpu(x) x ++/** Do nothing */ ++#define uap_le32_to_cpu(x) x ++/** Do nothing */ ++#define uap_le64_to_cpu(x) x ++/** Do nothing */ ++#define uap_cpu_to_le16(x) x ++/** Do nothing */ ++#define uap_cpu_to_le32(x) x ++/** Do nothing */ ++#define uap_cpu_to_le64(x) x ++ ++/** Do nothing */ ++#define endian_convert_TxPD(x) ++/** Do nothing */ ++#define endian_convert_RxPD(x) ++#endif /* BIG_ENDIAN */ ++ ++/** Host Command ID : Function initialization */ ++#define HostCmd_CMD_FUNC_INIT 0x00a9 ++/** Host Command ID : Function shutdown */ ++#define HostCmd_CMD_FUNC_SHUTDOWN 0x00aa ++ ++/** Host Command id: SYS_INFO */ ++#define HOST_CMD_APCMD_SYS_INFO 0x00ae ++/** Host Command id: SYS_RESET */ ++#define HOST_CMD_APCMD_SYS_RESET 0x00af ++/** Host Command id: SYS_CONFIGURE */ ++#define HOST_CMD_APCMD_SYS_CONFIGURE 0x00b0 ++/** Host Command id: BSS_START */ ++#define HOST_CMD_APCMD_BSS_START 0x00b1 ++/** Host Command id: SYS_STOP */ ++#define HOST_CMD_APCMD_BSS_STOP 0x00b2 ++/** Host Command id: STA_LIST */ ++#define HOST_CMD_APCMD_STA_LIST 0x00b3 ++/** Host Command id: STA_FILTER_TABLE */ ++#define HOST_CMD_APCMD_STA_FILTER_TABLE 0x00b4 ++/** Host Command id: STA_DEAUTH */ ++#define HOST_CMD_APCMD_STA_DEAUTH 0x00b5 ++/** Host Command id: SOFT_RESET */ ++#define HOST_CMD_APCMD_SOFT_RESET 0x00d5 ++/** Host Command id: POWER_MGMT_EXT */ ++#define HOST_CMD_POWER_MGMT_EXT 0x00ef ++/** Host Command id: SLEEP_CONFIRM*/ ++#define HOST_CMD_SLEEP_CONFIRM 0x00d8 ++ ++/** TLV type : SSID */ ++#define TLV_TYPE_SSID 0x0000 ++/** TLV type : Rates */ ++#define TLV_TYPE_RATES 0x0001 ++/** TLV type : PHY DS */ ++#define TLV_TYPE_PHY_DS 0x0003 ++ ++/** TLV Id : Base id */ ++#define PROPRIETARY_TLV_BASE_ID 0x0100 ++/** TLV Id : AP_MAC_ADDRESS */ ++#define MRVL_AP_MAC_ADDRESS_TLV_ID (PROPRIETARY_TLV_BASE_ID + 43) ++/** TLV Id : Beacon period */ ++#define MRVL_BEACON_PERIOD_TLV_ID (PROPRIETARY_TLV_BASE_ID + 44) ++/** TLV Id : Dtim period */ ++#define MRVL_DTIM_PERIOD_TLV_ID (PROPRIETARY_TLV_BASE_ID + 45) ++/** TLV Id : Basic rates */ ++#define MRVL_BASIC_RATES_TLV_ID (PROPRIETARY_TLV_BASE_ID + 46) ++/** TLV Id : Tx Power */ ++#define MRVL_TX_POWER_TLV_ID (PROPRIETARY_TLV_BASE_ID + 47) ++/** TLV Id : Broadcast SSID control */ ++#define MRVL_BCAST_SSID_CTL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 48) ++/** TLV Id : Preamble control */ ++#define MRVL_PREAMBLE_CTL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 49) ++/** TLV Id : Antenna control */ ++#define MRVL_ANTENNA_CTL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 50) ++/** TLV Id : RTS threshold */ ++#define MRVL_RTS_THRESHOLD_TLV_ID (PROPRIETARY_TLV_BASE_ID + 51) ++/** TLV Id : Radio control */ ++#define MRVL_RADIO_CTL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 52) ++/** TLV Id : TX data rate */ ++#define MRVL_TX_DATA_RATE_TLV_ID (PROPRIETARY_TLV_BASE_ID + 53) ++/** TLV Id : Packet forward control */ ++#define MRVL_PKT_FWD_CTL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 54) ++/** TLV Id : STA info */ ++#define MRVL_STA_INFO_TLV_ID (PROPRIETARY_TLV_BASE_ID + 55) ++/** TLV Id : STA MAC address filter */ ++#define MRVL_STA_MAC_ADDR_FILTER_TLV_ID (PROPRIETARY_TLV_BASE_ID + 56) ++/** TLV Id : STA ageout timer */ ++#define MRVL_STA_AGEOUT_TIMER_TLV_ID (PROPRIETARY_TLV_BASE_ID + 57) ++/** TLV Id : Security config */ ++#define MRVL_SECURITY_CFG_TLV_ID (PROPRIETARY_TLV_BASE_ID + 58) ++/** TLV Id : WEP KEY */ ++#define MRVL_WEP_KEY_TLV_ID (PROPRIETARY_TLV_BASE_ID + 59) ++/** TLV Id : WPA Passphrase */ ++#define MRVL_WPA_PASSPHRASE_TLV_ID (PROPRIETARY_TLV_BASE_ID + 60) ++ ++/** Action get */ ++#define ACTION_GET 0 ++/** Action set */ ++#define ACTION_SET 1 ++/** Length of ethernet address */ ++#ifndef ETH_ALEN ++#define ETH_ALEN 6 ++#endif ++ ++/** HostCmd_DS_GEN */ ++typedef struct ++{ ++ /** Command */ ++ u16 Command; ++ /** Size */ ++ u16 Size; ++ /** Sequence number */ ++ u16 SeqNum; ++ /** Result */ ++ u16 Result; ++} __ATTRIB_PACK__ HostCmd_DS_GEN; ++ ++/** Size of HostCmd_DS_GEN */ ++#define S_DS_GEN sizeof(HostCmd_DS_GEN) ++ ++/** _HostCmd_HEADER*/ ++typedef struct ++{ ++ /** Command Header : Command */ ++ u16 Command; ++ /** Command Header : Size */ ++ u16 Size; ++} __ATTRIB_PACK__ HostCmd_HEADER; ++ ++/** HostCmd_SYS_CONFIG */ ++typedef struct _HostCmd_SYS_CONFIG ++{ ++ /** CMD Action GET/SET*/ ++ u16 Action; ++ /** Tlv buffer */ ++ u8 TlvBuffer[0]; ++} __ATTRIB_PACK__ HostCmd_SYS_CONFIG; ++ ++/** HostCmd_DS_POWER_MGMT_EXT */ ++typedef struct _HostCmd_DS_POWER_MGMT_EXT ++{ ++ /** CMD Action Get/Set*/ ++ u16 action; ++ /** power mode */ ++ u16 power_mode; ++} __ATTRIB_PACK__ HostCmd_DS_POWER_MGMT_EXT; ++ ++/** _HostCmd_DS_COMMAND*/ ++typedef struct _HostCmd_DS_COMMAND ++{ ++ ++ /** Command Header : Command */ ++ u16 Command; ++ /** Command Header : Size */ ++ u16 Size; ++ /** Command Header : Sequence number */ ++ u16 SeqNum; ++ /** Command Header : Result */ ++ u16 Result; ++ /** Command Body */ ++ union ++ { ++ HostCmd_SYS_CONFIG sys_config; ++ HostCmd_DS_POWER_MGMT_EXT pm_cfg; ++ ++ } params; ++} __ATTRIB_PACK__ HostCmd_DS_COMMAND; ++ ++/** MrvlIEtypesHeader_*/ ++typedef struct _MrvlIEtypesHeader ++{ ++ /** Header type */ ++ u16 Type; ++ /** Header length */ ++ u16 Len; ++} __ATTRIB_PACK__ MrvlIEtypesHeader_t; ++ ++/** MrvlIEtypes_Data_t */ ++typedef struct _MrvlIEtypes_Data_t ++{ ++ /** Header */ ++ MrvlIEtypesHeader_t Header; ++ /** Data */ ++ u8 Data[1]; ++} __ATTRIB_PACK__ MrvlIEtypes_Data_t; ++ ++/** MrvlIEtypes_ChanListParamSet_t */ ++typedef struct _MrvlIEtypes_MacAddr_t ++{ ++ /** Header */ ++ MrvlIEtypesHeader_t Header; ++ /** AP MAC address */ ++ u8 ApMacAddr[ETH_ALEN]; ++} __ATTRIB_PACK__ MrvlIEtypes_MacAddr_t; ++ ++/** Event ID: BSS started */ ++#define MICRO_AP_EV_ID_BSS_START 46 ++ ++/** Event ID: BSS idle event */ ++#define MICRO_AP_EV_BSS_IDLE 67 ++ ++/** Event ID: BSS active event */ ++#define MICRO_AP_EV_BSS_ACTIVE 68 ++ ++/** Event ID: PS_AWAKE */ ++#define EVENT_PS_AWAKE 0x0a ++ ++/** Event ID: PS_SLEEP */ ++#define EVENT_PS_SLEEP 0x0b ++ ++/** PS_STATE */ ++typedef enum _PS_STATE ++{ ++ PS_STATE_AWAKE, ++ PS_STATE_PRE_SLEEP, ++ PS_STATE_SLEEP ++} PS_STATE; ++ ++/** TLV type: AP Sleep param */ ++#define TLV_TYPE_AP_SLEEP_PARAM (PROPRIETARY_TLV_BASE_ID + 106) ++/** TLV type: AP Inactivity Sleep param */ ++#define TLV_TYPE_AP_INACT_SLEEP_PARAM (PROPRIETARY_TLV_BASE_ID + 107) ++ ++/** MrvlIEtypes_sleep_param_t */ ++typedef struct _MrvlIEtypes_sleep_param_t ++{ ++ /** Header */ ++ MrvlIEtypesHeader_t header; ++ /** control bitmap */ ++ u32 ctrl_bitmap; ++ /** min_sleep */ ++ u32 min_sleep; ++ /** max_sleep */ ++ u32 max_sleep; ++} __ATTRIB_PACK__ MrvlIEtypes_sleep_param_t; ++ ++/** MrvlIEtypes_inact_sleep_param_t */ ++typedef struct _MrvlIEtypes_inact_sleep_param_t ++{ ++ /** Header */ ++ MrvlIEtypesHeader_t header; ++ /** inactivity timeout */ ++ u32 inactivity_to; ++ /** min_awake */ ++ u32 min_awake; ++ /** max_awake */ ++ u32 max_awake; ++} __ATTRIB_PACK__ MrvlIEtypes_inact_sleep_param_t; ++ ++/** AP_Event */ ++typedef struct _AP_Event ++{ ++ /** Event ID */ ++ u32 EventId; ++ /* ++ * Reserved for STA_ASSOCIATED event and contains ++ * status information for the MIC_COUNTERMEASURES event. ++ */ ++ /** Reserved/status */ ++ u16 status; ++ /** AP MAC address */ ++ u8 MacAddr[ETH_ALEN]; ++} __ATTRIB_PACK__ AP_Event; ++#endif /* _UAP_FW_H */ +diff -Naupr linux-2.6.37/drivers/net/wireless/libertas_uap/uap_headers.h linux-2.6.37-new/drivers/net/wireless/libertas_uap/uap_headers.h +--- linux-2.6.37/drivers/net/wireless/libertas_uap/uap_headers.h 1969-12-31 17:00:00.000000000 -0700 ++++ linux-2.6.37-new/drivers/net/wireless/libertas_uap/uap_headers.h 2011-01-08 06:01:04.043835537 -0700 +@@ -0,0 +1,64 @@ ++/** @file uap_headers.h ++ * ++ * @brief This file contains all the necessary include file. ++ * ++ * Copyright (C) 2008-2009, Marvell International Ltd. ++ * ++ * This software file (the "File") is distributed by Marvell International ++ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 ++ * (the "License"). You may use, redistribute and/or modify this File in ++ * accordance with the terms and conditions of the License, a copy of which ++ * is available along with the File in the gpl.txt file or by writing to ++ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. ++ * ++ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ++ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about ++ * this warranty disclaimer. ++ * ++ */ ++#ifndef _UAP_HEADERS_H ++#define _UAP_HEADERS_H ++ ++/* Linux header files */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) ++#include ++#else ++#include ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) ++#include ++#endif ++ ++/* Net header files */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "uap_drv.h" ++#include "uap_fw.h" ++ ++#include ++#include ++#include ++#include ++#include "uap_sdio_mmc.h" ++ ++#endif /* _UAP_HEADERS_H */ +diff -Naupr linux-2.6.37/drivers/net/wireless/libertas_uap/uap_main.c linux-2.6.37-new/drivers/net/wireless/libertas_uap/uap_main.c +--- linux-2.6.37/drivers/net/wireless/libertas_uap/uap_main.c 1969-12-31 17:00:00.000000000 -0700 ++++ linux-2.6.37-new/drivers/net/wireless/libertas_uap/uap_main.c 2011-01-08 06:01:04.048835193 -0700 +@@ -0,0 +1,1830 @@ ++/** @file uap_main.c ++ * @brief This file contains the major functions in uAP ++ * driver. It includes init, exit etc.. ++ * This file also contains the initialization for SW, ++ * FW and HW ++ * ++ * Copyright (C) 2008-2009, Marvell International Ltd. ++ * ++ * This software file (the "File") is distributed by Marvell International ++ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 ++ * (the "License"). You may use, redistribute and/or modify this File in ++ * accordance with the terms and conditions of the License, a copy of which ++ * is available along with the File in the gpl.txt file or by writing to ++ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. ++ * ++ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ++ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about ++ * this warranty disclaimer. ++ * ++ */ ++/** ++ * @mainpage uAP Linux Driver ++ * ++ * @section overview_sec Overview ++ * ++ * This is Linux reference driver for Marvell uAP. ++ * ++ * @section copyright_sec Copyright ++ * ++ * Copyright (C) 2008, Marvell International Ltd. ++ * ++ */ ++ ++#include "uap_headers.h" ++ ++/** ++ * the global variable of a pointer to uap_private ++ * structure variable ++ */ ++uap_private *uappriv = NULL; ++#ifdef DEBUG_LEVEL1 ++#define DEFAULT_DEBUG_MASK (DBG_MSG | DBG_FATAL | DBG_ERROR) ++u32 drvdbg = DEFAULT_DEBUG_MASK; ++#endif ++/** Helper name */ ++char *helper_name = NULL; ++/** Firmware name */ ++char *fw_name = NULL; ++ ++/** Semaphore for add/remove card */ ++SEMAPHORE AddRemoveCardSem; ++ ++/******************************************************** ++ Local Functions ++********************************************************/ ++/** ++ * @brief This function send sleep confirm command to firmware ++ * ++ * @param priv A pointer to uap_private structure ++ * @return UAP_STATUS_SUCCESS for success otherwise UAP_STATUS_FAILURE ++ */ ++static int ++uap_dnld_sleep_confirm_cmd(uap_private * priv) ++{ ++ uap_adapter *Adapter = priv->adapter; ++ int ret = UAP_STATUS_SUCCESS; ++ ENTER(); ++ PRINTM(CMND, "Sleep confirm\n"); ++ Adapter->cmd_pending = TRUE; ++ Adapter->cmd_wait_option = HostCmd_OPTION_WAITFORRSP_SLEEPCONFIRM; ++ ret = ++ sbi_host_to_card(priv, (u8 *) & Adapter->PSConfirmSleep, ++ sizeof(PS_CMD_ConfirmSleep)); ++ if (ret != UAP_STATUS_SUCCESS) { ++ Adapter->ps_state = PS_STATE_AWAKE; ++ Adapter->cmd_pending = FALSE; ++ Adapter->cmd_wait_option = FALSE; ++ } ++ LEAVE(); ++ return ret; ++} ++ ++/** ++ * @brief This function process sleep confirm resp from firmware ++ * ++ * @param priv A pointer to uap_private structure ++ * @param resp A pointer to resp buf ++ * @param resp_len resp buf len ++ * @return UAP_STATUS_SUCCESS for success otherwise UAP_STATUS_FAILURE ++ */ ++int ++uap_process_sleep_confirm_resp(uap_private * priv, u8 * resp, int resp_len) ++{ ++ int ret = UAP_STATUS_SUCCESS; ++ HostCmd_DS_COMMAND *cmd; ++ uap_adapter *Adapter = priv->adapter; ++ ENTER(); ++ PRINTM(CMND, "Sleep confirm resp\n"); ++ if (!resp_len) { ++ PRINTM(ERROR, "Cmd Size is 0\n"); ++ ret = -EFAULT; ++ goto done; ++ } ++ cmd = (HostCmd_DS_COMMAND *) resp; ++ cmd->Result = uap_le16_to_cpu(cmd->Result); ++ if (cmd->Result != UAP_STATUS_SUCCESS) { ++ PRINTM(ERROR, "HOST_CMD_APCMD_PS_SLEEP_CONFIRM fail=%x\n", cmd->Result); ++ ret = -EFAULT; ++ } ++ done: ++ if (ret == UAP_STATUS_SUCCESS) ++ Adapter->ps_state = PS_STATE_SLEEP; ++ else ++ Adapter->ps_state = PS_STATE_AWAKE; ++ LEAVE(); ++ return ret; ++} ++ ++/** ++ * @brief This function checks condition and prepares to ++ * send sleep confirm command to firmware if OK. ++ * ++ * @param priv A pointer to uap_private structure ++ * @return n/a ++ */ ++static void ++uap_ps_cond_check(uap_private * priv) ++{ ++ uap_adapter *Adapter = priv->adapter; ++ ++ ENTER(); ++ if (!priv->uap_dev.cmd_sent && ++ !Adapter->cmd_pending && !Adapter->IntCounter) { ++ uap_dnld_sleep_confirm_cmd(priv); ++ } else { ++ PRINTM(INFO, "Delay Sleep Confirm (%s%s%s)\n", ++ (priv->uap_dev.cmd_sent) ? "D" : "", ++ (Adapter->cmd_pending) ? "C" : "", ++ (Adapter->IntCounter) ? "I" : ""); ++ } ++ LEAVE(); ++} ++ ++/** ++ * @brief This function add cmd to cmdQ and waiting for response ++ * ++ * @param priv A pointer to uap_private structure ++ * @param skb A pointer to the skb for process ++ * @param wait_option Wait option ++ * @return UAP_STATUS_SUCCESS for success otherwise UAP_STATUS_FAILURE ++ */ ++static int ++uap_process_cmd(uap_private * priv, struct sk_buff *skb, u8 wait_option) ++{ ++ uap_adapter *Adapter = priv->adapter; ++ int ret = UAP_STATUS_SUCCESS; ++ HostCmd_DS_COMMAND *cmd; ++ u8 *headptr; ++ ENTER(); ++ if (Adapter->HardwareStatus != HWReady) { ++ PRINTM(ERROR, "Hw not ready, uap_process_cmd\n"); ++ kfree(skb); ++ LEAVE(); ++ return -EFAULT; ++ } ++ skb->cb[0] = wait_option; ++ headptr = skb->data; ++ *(u16 *) & headptr[0] = uap_cpu_to_le16(skb->len); ++ *(u16 *) & headptr[2] = uap_cpu_to_le16(MV_TYPE_CMD); ++ cmd = (HostCmd_DS_COMMAND *) (skb->data + INTF_HEADER_LEN); ++ Adapter->SeqNum++; ++ cmd->SeqNum = uap_cpu_to_le16(Adapter->SeqNum); ++ PRINTM(CMND, "process_cmd: %x\n", cmd->Command); ++ DBG_HEXDUMP(CMD_D, "process_cmd", (u8 *) cmd, cmd->Size); ++ if (!wait_option) { ++ skb_queue_tail(&priv->adapter->cmd_queue, skb); ++ wake_up_interruptible(&priv->MainThread.waitQ); ++ LEAVE(); ++ return ret; ++ } ++ if (OS_ACQ_SEMAPHORE_BLOCK(&Adapter->CmdSem)) { ++ PRINTM(ERROR, "Acquire semaphore error, uap_prepare_cmd\n"); ++ kfree(skb); ++ LEAVE(); ++ return -EBUSY; ++ } ++ skb_queue_tail(&priv->adapter->cmd_queue, skb); ++ Adapter->CmdWaitQWoken = FALSE; ++ wake_up_interruptible(&priv->MainThread.waitQ); ++ /* Sleep until response is generated by FW */ ++ if (wait_option == HostCmd_OPTION_WAITFORRSP_TIMEOUT) { ++ if (!os_wait_interruptible_timeout ++ (Adapter->cmdwait_q, Adapter->CmdWaitQWoken, MRVDRV_TIMER_20S)) { ++ PRINTM(ERROR, "Cmd timeout\n"); ++ Adapter->cmd_pending = FALSE; ++ ret = -EFAULT; ++ } ++ } else ++ wait_event_interruptible(Adapter->cmdwait_q, Adapter->CmdWaitQWoken); ++ OS_REL_SEMAPHORE(&Adapter->CmdSem); ++ LEAVE(); ++ return ret; ++} ++ ++/** ++ * @brief Inspect the response buffer for pointers to expected TLVs ++ * ++ * ++ * @param pTlv Pointer to the start of the TLV buffer to parse ++ * @param tlvBufSize Size of the TLV buffer ++ * @param reqTlvType request tlv's tlvtype ++ * @param ppTlv Output parameter: Pointer to the request TLV if found ++ * ++ * @return void ++ */ ++static void ++uap_get_tlv_ptrs(MrvlIEtypes_Data_t * pTlv, int tlvBufSize, ++ u16 reqTlvType, MrvlIEtypes_Data_t ** ppTlv) ++{ ++ MrvlIEtypes_Data_t *pCurrentTlv; ++ int tlvBufLeft; ++ u16 tlvType; ++ u16 tlvLen; ++ ++ ENTER(); ++ pCurrentTlv = pTlv; ++ tlvBufLeft = tlvBufSize; ++ *ppTlv = NULL; ++ PRINTM(INFO, "uap_get_tlv: tlvBufSize = %d, reqTlvType=%x\n", tlvBufSize, ++ reqTlvType); ++ while (tlvBufLeft >= sizeof(MrvlIEtypesHeader_t)) { ++ tlvType = uap_le16_to_cpu(pCurrentTlv->Header.Type); ++ tlvLen = uap_le16_to_cpu(pCurrentTlv->Header.Len); ++ if (reqTlvType == tlvType) ++ *ppTlv = (MrvlIEtypes_Data_t *) pCurrentTlv; ++ if (*ppTlv) { ++ HEXDUMP("TLV Buf", (u8 *) * ppTlv, tlvLen); ++ break; ++ } ++ tlvBufLeft -= (sizeof(pTlv->Header) + tlvLen); ++ pCurrentTlv = (MrvlIEtypes_Data_t *) (pCurrentTlv->Data + tlvLen); ++ } /* while */ ++ LEAVE(); ++} ++ ++/** ++ * @brief This function get mac ++ * ++ * @param priv A pointer to uap_private structure ++ * @return UAP_STATUS_SUCCESS on success, otherwise failure code ++ */ ++static int ++uap_get_mac_address(uap_private * priv) ++{ ++ int ret = UAP_STATUS_SUCCESS; ++ u32 CmdSize; ++ HostCmd_DS_COMMAND *cmd; ++ uap_adapter *Adapter = priv->adapter; ++ struct sk_buff *skb; ++ MrvlIEtypes_MacAddr_t *pMacAddrTlv; ++ MrvlIEtypes_Data_t *pTlv; ++ u16 tlvBufSize; ++ ENTER(); ++ skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER); ++ if (!skb) { ++ PRINTM(ERROR, "No free skb\n"); ++ ret = -ENOMEM; ++ goto done; ++ } ++ CmdSize = ++ S_DS_GEN + sizeof(HostCmd_SYS_CONFIG) + sizeof(MrvlIEtypes_MacAddr_t); ++ cmd = (HostCmd_DS_COMMAND *) (skb->data + INTF_HEADER_LEN); ++ cmd->Command = uap_cpu_to_le16(HOST_CMD_APCMD_SYS_CONFIGURE); ++ cmd->Size = uap_cpu_to_le16(CmdSize); ++ cmd->params.sys_config.Action = uap_cpu_to_le16(ACTION_GET); ++ pMacAddrTlv = ++ (MrvlIEtypes_MacAddr_t *) (skb->data + INTF_HEADER_LEN + S_DS_GEN + ++ sizeof(HostCmd_SYS_CONFIG)); ++ pMacAddrTlv->Header.Type = uap_cpu_to_le16(MRVL_AP_MAC_ADDRESS_TLV_ID); ++ pMacAddrTlv->Header.Len = uap_cpu_to_le16(ETH_ALEN); ++ skb_put(skb, CmdSize + INTF_HEADER_LEN); ++ if (UAP_STATUS_SUCCESS != ++ uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP_TIMEOUT)) { ++ PRINTM(ERROR, "Fail to process cmd SYS_CONFIGURE Query\n"); ++ ret = -EFAULT; ++ goto done; ++ } ++ if (!Adapter->CmdSize) { ++ PRINTM(ERROR, "Cmd Size is 0\n"); ++ ret = -EFAULT; ++ goto done; ++ } ++ cmd = (HostCmd_DS_COMMAND *) Adapter->CmdBuf; ++ cmd->Result = uap_le16_to_cpu(cmd->Result); ++ if (cmd->Result != UAP_STATUS_SUCCESS) { ++ PRINTM(ERROR, "uap_get_mac_address fail=%x\n", cmd->Result); ++ ret = -EFAULT; ++ goto done; ++ } ++ pTlv = ++ (MrvlIEtypes_Data_t *) (Adapter->CmdBuf + S_DS_GEN + ++ sizeof(HostCmd_SYS_CONFIG)); ++ tlvBufSize = Adapter->CmdSize - S_DS_GEN - sizeof(HostCmd_SYS_CONFIG); ++ uap_get_tlv_ptrs(pTlv, tlvBufSize, MRVL_AP_MAC_ADDRESS_TLV_ID, ++ (MrvlIEtypes_Data_t **) & pMacAddrTlv); ++ if (pMacAddrTlv) { ++ memcpy(priv->uap_dev.netdev->dev_addr, pMacAddrTlv->ApMacAddr, ++ ETH_ALEN); ++ HEXDUMP("Original MAC addr", priv->uap_dev.netdev->dev_addr, ETH_ALEN); ++ } ++ done: ++ LEAVE(); ++ return ret; ++} ++ ++/** ++ * @brief This function checks the conditions and sends packet to device ++ * ++ * @param priv A pointer to uap_private structure ++ * @param skb A pointer to the skb for process ++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE ++ */ ++static int ++uap_process_tx(uap_private * priv, struct sk_buff *skb) ++{ ++ uap_adapter *Adapter = priv->adapter; ++ int ret = UAP_STATUS_SUCCESS; ++ TxPD *pLocalTxPD; ++ u8 *headptr; ++ struct sk_buff *newskb; ++ int newheadlen; ++ ENTER(); ++ ASSERT(skb); ++ if (!skb) { ++ LEAVE(); ++ return UAP_STATUS_FAILURE; ++ } ++ if (skb_headroom(skb) < (sizeof(TxPD) + INTF_HEADER_LEN + HEADER_ALIGNMENT)) { ++ newheadlen = sizeof(TxPD) + INTF_HEADER_LEN + HEADER_ALIGNMENT; ++ PRINTM(WARN, "Tx: Insufficient skb headroom %d\n", skb_headroom(skb)); ++ /* Insufficient skb headroom - allocate a new skb */ ++ newskb = skb_realloc_headroom(skb, newheadlen); ++ if (unlikely(newskb == NULL)) { ++ PRINTM(ERROR, "Tx: Cannot allocate skb\n"); ++ ret = UAP_STATUS_FAILURE; ++ goto done; ++ } ++ kfree_skb(skb); ++ skb = newskb; ++ PRINTM(INFO, "new skb headroom %d\n", skb_headroom(skb)); ++ } ++ /* headptr should be aligned */ ++ headptr = skb->data - sizeof(TxPD) - INTF_HEADER_LEN; ++ headptr = (u8 *) ((u32) headptr & ~((u32) (HEADER_ALIGNMENT - 1))); ++ ++ pLocalTxPD = (TxPD *) (headptr + INTF_HEADER_LEN); ++ memset(pLocalTxPD, 0, sizeof(TxPD)); ++ pLocalTxPD->BssType = PKT_TYPE_MICROAP; ++ pLocalTxPD->TxPktLength = skb->len; ++ /* offset of actual data */ ++ pLocalTxPD->TxPktOffset = (long) skb->data - (long) pLocalTxPD; ++ endian_convert_TxPD(pLocalTxPD); ++ *(u16 *) & headptr[0] = ++ uap_cpu_to_le16(skb->len + ((long) skb->data - (long) headptr)); ++ *(u16 *) & headptr[2] = uap_cpu_to_le16(MV_TYPE_DAT); ++ ret = ++ sbi_host_to_card(priv, headptr, ++ skb->len + ((long) skb->data - (long) headptr)); ++ if (ret) { ++ PRINTM(ERROR, "uap_process_tx Error: sbi_host_to_card failed: 0x%X\n", ++ ret); ++ Adapter->dbg.num_tx_host_to_card_failure++; ++ goto done; ++ } ++ PRINTM(DATA, "Data => FW\n"); ++ DBG_HEXDUMP(DAT_D, "Tx", headptr, ++ MIN(skb->len + sizeof(TxPD), DATA_DUMP_LEN)); ++ done: ++ /* Freed skb */ ++ kfree_skb(skb); ++ LEAVE(); ++ return ret; ++} ++ ++/** ++ * @brief This function initializes the adapter structure ++ * and set default value to the member of adapter. ++ * ++ * @param priv A pointer to uap_private structure ++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE ++ */ ++static int ++uap_init_sw(uap_private * priv) ++{ ++ uap_adapter *Adapter = priv->adapter; ++ ++ ENTER(); ++ ++ if (!(Adapter->CmdBuf = kmalloc(MRVDRV_SIZE_OF_CMD_BUFFER, GFP_KERNEL))) { ++ PRINTM(INFO, "Failed to allocate command buffer!\n"); ++ LEAVE(); ++ return UAP_STATUS_FAILURE; ++ } ++ ++ Adapter->cmd_pending = FALSE; ++ Adapter->CmdWaitQWoken = FALSE; ++ Adapter->ps_state = PS_STATE_AWAKE; ++ Adapter->WakeupTries = 0; ++ ++ memset(&Adapter->PSConfirmSleep, 0, sizeof(PS_CMD_ConfirmSleep)); ++ /** SDIO header */ ++ Adapter->PSConfirmSleep.SDLen = ++ uap_cpu_to_le16(sizeof(PS_CMD_ConfirmSleep)); ++ Adapter->PSConfirmSleep.SDType = uap_cpu_to_le16(MV_TYPE_CMD); ++ Adapter->PSConfirmSleep.SeqNum = 0; ++ Adapter->PSConfirmSleep.Command = uap_cpu_to_le16(HOST_CMD_SLEEP_CONFIRM); ++ Adapter->PSConfirmSleep.Size = uap_cpu_to_le16(sizeof(HostCmd_DS_GEN)); ++ Adapter->PSConfirmSleep.Result = 0; ++ ++ init_waitqueue_head(&Adapter->cmdwait_q); ++ OS_INIT_SEMAPHORE(&Adapter->CmdSem); ++ ++ skb_queue_head_init(&Adapter->tx_queue); ++ skb_queue_head_init(&Adapter->cmd_queue); ++ ++ /* Status variable */ ++ Adapter->HardwareStatus = HWInitializing; ++ ++ /* PnP support */ ++ Adapter->SurpriseRemoved = FALSE; ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) ++ Adapter->nl_sk = netlink_kernel_create(NETLINK_MARVELL, ++ NL_MULTICAST_GROUP, NULL, ++ THIS_MODULE); ++#else ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) ++ Adapter->nl_sk = netlink_kernel_create(NETLINK_MARVELL, ++ NL_MULTICAST_GROUP, NULL, NULL, ++ THIS_MODULE); ++#else ++ Adapter->nl_sk = netlink_kernel_create(&init_net, NETLINK_MARVELL, ++ NL_MULTICAST_GROUP, NULL, NULL, ++ THIS_MODULE); ++#endif ++#endif ++ if (!Adapter->nl_sk) { ++ PRINTM(ERROR, ++ "Could not initialize netlink event passing mechanism!\n"); ++ } ++ LEAVE(); ++ return UAP_STATUS_SUCCESS; ++} ++ ++/** ++ * @brief This function sends FUNC_INIT command to firmware ++ * ++ * @param priv A pointer to uap_private structure ++ * @return UAP_STATUS_SUCCESS on success, otherwise failure code ++ */ ++static int ++uap_func_init(uap_private * priv) ++{ ++ int ret = UAP_STATUS_SUCCESS; ++ u32 CmdSize; ++ HostCmd_DS_GEN *cmd; ++ uap_adapter *Adapter = priv->adapter; ++ struct sk_buff *skb; ++ ENTER(); ++ if (Adapter->HardwareStatus != HWReady) { ++ PRINTM(ERROR, "uap_func_init:Hardware is not ready!\n"); ++ ret = -EFAULT; ++ goto done; ++ } ++ skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER); ++ if (!skb) { ++ PRINTM(ERROR, "No free skb\n"); ++ ret = -ENOMEM; ++ goto done; ++ } ++ CmdSize = sizeof(HostCmd_DS_GEN); ++ cmd = (HostCmd_DS_GEN *) (skb->data + INTF_HEADER_LEN); ++ cmd->Command = uap_cpu_to_le16(HostCmd_CMD_FUNC_INIT); ++ cmd->Size = uap_cpu_to_le16(CmdSize); ++ skb_put(skb, CmdSize + INTF_HEADER_LEN); ++ PRINTM(CMND, "HostCmd_CMD_FUNC_INIT\n"); ++ if (UAP_STATUS_SUCCESS != ++ uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP_TIMEOUT)) { ++ PRINTM(ERROR, "Fail to process cmd HostCmd_CMD_FUNC_INIT\n"); ++ ret = -EFAULT; ++ goto done; ++ } ++ done: ++ LEAVE(); ++ return ret; ++} ++ ++/** ++ * @brief This function sends FUNC_SHUTDOWN command to firmware ++ * ++ * @param priv A pointer to uap_private structure ++ * @return UAP_STATUS_SUCCESS on success, otherwise failure code ++ */ ++static int __exit ++uap_func_shutdown(uap_private * priv) ++{ ++ int ret = UAP_STATUS_SUCCESS; ++ u32 CmdSize; ++ HostCmd_DS_GEN *cmd; ++ uap_adapter *Adapter = priv->adapter; ++ struct sk_buff *skb; ++ ENTER(); ++ if (Adapter->HardwareStatus != HWReady) { ++ PRINTM(ERROR, "uap_func_shutdown:Hardware is not ready!\n"); ++ ret = -EFAULT; ++ goto done; ++ } ++ skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER); ++ if (!skb) { ++ PRINTM(ERROR, "No free skb\n"); ++ ret = -ENOMEM; ++ goto done; ++ } ++ CmdSize = sizeof(HostCmd_DS_GEN); ++ cmd = (HostCmd_DS_GEN *) (skb->data + INTF_HEADER_LEN); ++ cmd->Command = uap_cpu_to_le16(HostCmd_CMD_FUNC_SHUTDOWN); ++ cmd->Size = uap_cpu_to_le16(CmdSize); ++ skb_put(skb, CmdSize + INTF_HEADER_LEN); ++ PRINTM(CMND, "HostCmd_CMD_FUNC_SHUTDOWN\n"); ++ if (UAP_STATUS_SUCCESS != ++ uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP_TIMEOUT)) { ++ PRINTM(ERROR, "Fail to process cmd HostCmd_CMD_FUNC_SHUTDOWN\n"); ++ ret = -EFAULT; ++ goto done; ++ } ++ done: ++ LEAVE(); ++ return ret; ++} ++ ++/** ++ * @brief This function initializes firmware ++ * ++ * @param priv A pointer to uap_private structure ++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE ++ */ ++static int ++uap_init_fw(uap_private * priv) ++{ ++ int ret = UAP_STATUS_SUCCESS; ++ ENTER(); ++ sbi_disable_host_int(priv); ++ /* Check if firmware is already running */ ++ if (sbi_check_fw_status(priv, 1) == UAP_STATUS_SUCCESS) { ++ PRINTM(MSG, "UAP FW already running! Skip FW download\n"); ++ } else { ++ if ((ret = request_firmware(&priv->fw_helper, helper_name, ++ priv->hotplug_device)) < 0) { ++ PRINTM(FATAL, ++ "request_firmware() failed (helper), error code = %#x\n", ++ ret); ++ goto done; ++ } ++ ++ /* Download the helper */ ++ ret = sbi_prog_helper(priv); ++ ++ if (ret) { ++ PRINTM(FATAL, ++ "Bootloader in invalid state! Helper download failed!\n"); ++ ret = UAP_STATUS_FAILURE; ++ goto done; ++ } ++ if ((ret = request_firmware(&priv->firmware, fw_name, ++ priv->hotplug_device)) < 0) { ++ PRINTM(FATAL, "request_firmware() failed, error code = %#x\n", ret); ++ goto done; ++ } ++ ++ /* Download the main firmware via the helper firmware */ ++ if (sbi_prog_fw_w_helper(priv)) { ++ PRINTM(FATAL, "UAP FW download failed!\n"); ++ ret = UAP_STATUS_FAILURE; ++ goto done; ++ } ++ /* Check if the firmware is downloaded successfully or not */ ++ if (sbi_check_fw_status(priv, MAX_FIRMWARE_POLL_TRIES) == ++ UAP_STATUS_FAILURE) { ++ PRINTM(FATAL, "FW failed to be active in time!\n"); ++ ret = UAP_STATUS_FAILURE; ++ goto done; ++ } ++ PRINTM(MSG, "UAP FW is active\n"); ++ } ++ sbi_enable_host_int(priv); ++ priv->adapter->HardwareStatus = HWReady; ++ if (uap_func_init(priv) != UAP_STATUS_SUCCESS) { ++ ret = UAP_STATUS_FAILURE; ++ goto done; ++ } ++ done: ++ if (priv->fw_helper) ++ release_firmware(priv->fw_helper); ++ if (priv->firmware) ++ release_firmware(priv->firmware); ++ LEAVE(); ++ return ret; ++ ++} ++ ++/** ++ * @brief This function frees the structure of adapter ++ * ++ * @param priv A pointer to uap_private structure ++ * @return n/a ++ */ ++static void ++uap_free_adapter(uap_private * priv) ++{ ++ uap_adapter *Adapter = priv->adapter; ++ ++ ENTER(); ++ ++ if (Adapter) { ++ if ((Adapter->nl_sk) && ((Adapter->nl_sk)->sk_socket)) { ++ sock_release((Adapter->nl_sk)->sk_socket); ++ Adapter->nl_sk = NULL; ++ } ++ if (Adapter->CmdBuf) ++ kfree(Adapter->CmdBuf); ++ skb_queue_purge(&priv->adapter->tx_queue); ++ skb_queue_purge(&priv->adapter->cmd_queue); ++ /* Free the adapter object itself */ ++ kfree(Adapter); ++ priv->adapter = NULL; ++ } ++ ++ LEAVE(); ++} ++ ++/** ++ * @brief This function handles the major job in uap driver. ++ * it handles the event generated by firmware, rx data received ++ * from firmware and tx data sent from kernel. ++ * ++ * @param data A pointer to uap_thread structure ++ * @return BT_STATUS_SUCCESS ++ */ ++static int ++uap_service_main_thread(void *data) ++{ ++ uap_thread *thread = data; ++ uap_private *priv = thread->priv; ++ uap_adapter *Adapter = priv->adapter; ++ wait_queue_t wait; ++ u8 ireg = 0; ++ struct sk_buff *skb; ++ ENTER(); ++ uap_activate_thread(thread); ++ init_waitqueue_entry(&wait, current); ++ current->flags |= PF_NOFREEZE; ++ ++ for (;;) { ++ add_wait_queue(&thread->waitQ, &wait); ++ OS_SET_THREAD_STATE(TASK_INTERRUPTIBLE); ++ if ((Adapter->WakeupTries) || ++ (!Adapter->IntCounter && Adapter->ps_state == PS_STATE_PRE_SLEEP) || ++ (!priv->adapter->IntCounter ++ && (priv->uap_dev.data_sent || ++ skb_queue_empty(&priv->adapter->tx_queue)) ++ && (priv->uap_dev.cmd_sent || Adapter->cmd_pending || ++ skb_queue_empty(&priv->adapter->cmd_queue)) ++ )) { ++ PRINTM(INFO, "Main: Thread sleeping...\n"); ++ schedule(); ++ } ++ OS_SET_THREAD_STATE(TASK_RUNNING); ++ remove_wait_queue(&thread->waitQ, &wait); ++ if (kthread_should_stop() || Adapter->SurpriseRemoved) { ++ PRINTM(INFO, "main-thread: break from main thread: " ++ "SurpriseRemoved=0x%x\n", Adapter->SurpriseRemoved); ++ /* Cancel pending command */ ++ if (Adapter->cmd_pending == TRUE) { ++ /* Wake up cmd Q */ ++ Adapter->CmdWaitQWoken = TRUE; ++ wake_up_interruptible(&Adapter->cmdwait_q); ++ } ++ break; ++ } ++ ++ PRINTM(INFO, "Main: Thread waking up...\n"); ++ if (priv->adapter->IntCounter) { ++ OS_INT_DISABLE; ++ Adapter->IntCounter = 0; ++ OS_INT_RESTORE; ++ sbi_get_int_status(priv, &ireg); ++ } else if ((priv->adapter->ps_state == PS_STATE_SLEEP) && ++ (!skb_queue_empty(&priv->adapter->cmd_queue) || ++ !skb_queue_empty(&priv->adapter->tx_queue))) { ++ priv->adapter->WakeupTries++; ++ PRINTM(CMND, "%lu : Wakeup device...\n", os_time_get()); ++ sbi_wakeup_firmware(priv); ++ continue; ++ } ++ if (Adapter->ps_state == PS_STATE_PRE_SLEEP) ++ uap_ps_cond_check(priv); ++ ++ /* The PS state is changed during processing of Sleep Request event ++ above */ ++ if ((Adapter->ps_state == PS_STATE_SLEEP) || ++ (Adapter->ps_state == PS_STATE_PRE_SLEEP)) ++ continue; ++ /* Execute the next command */ ++ if (!priv->uap_dev.cmd_sent && !Adapter->cmd_pending && ++ (Adapter->HardwareStatus == HWReady)) { ++ if (!skb_queue_empty(&priv->adapter->cmd_queue)) { ++ skb = skb_dequeue(&priv->adapter->cmd_queue); ++ if (skb) { ++ Adapter->CmdSize = 0; ++ Adapter->cmd_pending = TRUE; ++ Adapter->cmd_wait_option = skb->cb[0]; ++ if (sbi_host_to_card(priv, skb->data, skb->len)) { ++ PRINTM(ERROR, "Cmd:sbi_host_to_card failed!\n"); ++ Adapter->cmd_pending = FALSE; ++ Adapter->dbg.num_cmd_host_to_card_failure++; ++ /* Wake up cmd Q */ ++ Adapter->CmdWaitQWoken = TRUE; ++ wake_up_interruptible(&Adapter->cmdwait_q); ++ } else { ++ if (Adapter->cmd_wait_option == ++ HostCmd_OPTION_WAITFORSEND) { ++ /* Wake up cmd Q */ ++ Adapter->CmdWaitQWoken = TRUE; ++ wake_up_interruptible(&Adapter->cmdwait_q); ++ Adapter->cmd_wait_option = FALSE; ++ } ++ } ++ kfree_skb(skb); ++ } ++ } ++ } ++ if (!priv->uap_dev.data_sent && (Adapter->HardwareStatus == HWReady)) { ++ if (!skb_queue_empty(&priv->adapter->tx_queue)) { ++ skb = skb_dequeue(&priv->adapter->tx_queue); ++ if (skb) { ++ if (uap_process_tx(priv, skb)) { ++ priv->stats.tx_dropped++; ++ priv->stats.tx_errors++; ++ os_start_queue(priv); ++ } else { ++ priv->stats.tx_packets++; ++ priv->stats.tx_bytes += skb->len; ++ } ++ ++ } ++ } ++ } ++ } ++ uap_deactivate_thread(thread); ++ LEAVE(); ++ return UAP_STATUS_SUCCESS; ++} ++ ++/** ++ * @brief uap hostcmd ioctl handler ++ * ++ * @param dev A pointer to net_device structure ++ * @param req A pointer to ifreq structure ++ * @return UAP_STATUS_SUCCESS --success, otherwise fail ++ */ ++/********* format of ifr_data *************/ ++/* buf_len + Hostcmd_body */ ++/* buf_len: 4 bytes */ ++/* the length of the buf which */ ++/* can be used to return data */ ++/* to application */ ++/* Hostcmd_body */ ++/*******************************************/ ++static int ++uap_hostcmd_ioctl(struct net_device *dev, struct ifreq *req) ++{ ++ u32 buf_len; ++ HostCmd_HEADER head; ++ uap_private *priv = (uap_private *) netdev_priv(dev); ++ uap_adapter *Adapter = priv->adapter; ++ int ret = UAP_STATUS_SUCCESS; ++ struct sk_buff *skb; ++ ++ ENTER(); ++ ++ /* Sanity check */ ++ if (req->ifr_data == NULL) { ++ PRINTM(ERROR, "uap_hostcmd_ioctl() corrupt data\n"); ++ LEAVE(); ++ return -EFAULT; ++ } ++ if (copy_from_user(&buf_len, req->ifr_data, sizeof(buf_len))) { ++ PRINTM(ERROR, "Copy from user failed\n"); ++ LEAVE(); ++ return -EFAULT; ++ } ++ memset(&head, 0, sizeof(HostCmd_HEADER)); ++ /* Get the command size from user space */ ++ if (copy_from_user ++ (&head, req->ifr_data + sizeof(buf_len), sizeof(HostCmd_HEADER))) { ++ PRINTM(ERROR, "Copy from user failed\n"); ++ LEAVE(); ++ return -EFAULT; ++ } ++ head.Size = uap_le16_to_cpu(head.Size); ++ if (head.Size > MRVDRV_SIZE_OF_CMD_BUFFER) { ++ PRINTM(ERROR, "CmdSize too big=%d\n", head.Size); ++ LEAVE(); ++ return -EFAULT; ++ } ++ PRINTM(CMND, "ioctl: hostcmd=%x, size=%d,buf_len=%d\n", head.Command, ++ head.Size, buf_len); ++ skb = dev_alloc_skb(head.Size + INTF_HEADER_LEN); ++ if (!skb) { ++ PRINTM(ERROR, "No free skb\n"); ++ LEAVE(); ++ return -ENOMEM; ++ } ++ ++ /* Get the command from user space */ ++ if (copy_from_user ++ (skb->data + INTF_HEADER_LEN, req->ifr_data + sizeof(buf_len), ++ head.Size)) { ++ PRINTM(ERROR, "Copy from user failed\n"); ++ LEAVE(); ++ return -EFAULT; ++ } ++ skb_put(skb, head.Size + INTF_HEADER_LEN); ++ if (UAP_STATUS_SUCCESS != ++ uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP)) { ++ PRINTM(ERROR, "Fail to process cmd\n"); ++ LEAVE(); ++ return -EFAULT; ++ } ++ if (!Adapter->CmdSize) { ++ PRINTM(ERROR, "Cmd Size is 0\n"); ++ LEAVE(); ++ return -EFAULT; ++ } ++ if (Adapter->CmdSize > buf_len) { ++ PRINTM(ERROR, "buf_len is too small\n"); ++ LEAVE(); ++ return -EFAULT; ++ } ++ /* Copy to user */ ++ if (copy_to_user ++ (req->ifr_data + sizeof(buf_len), Adapter->CmdBuf, Adapter->CmdSize)) { ++ PRINTM(ERROR, "Copy to user failed!\n"); ++ LEAVE(); ++ return -EFAULT; ++ } ++ LEAVE(); ++ return ret; ++} ++ ++/** ++ * @brief uap power mode ioctl handler ++ * ++ * @param dev A pointer to net_device structure ++ * @param req A pointer to ifreq structure ++ * @return UAP_STATUS_SUCCESS --success, otherwise fail ++ */ ++static int ++uap_power_mode_ioctl(struct net_device *dev, struct ifreq *req) ++{ ++ ps_mgmt pm_cfg; ++ int ret = UAP_STATUS_SUCCESS; ++ uap_private *priv = (uap_private *) netdev_priv(dev); ++ uap_adapter *Adapter = priv->adapter; ++ struct sk_buff *skb = NULL; ++ HostCmd_DS_COMMAND *cmd; ++ u32 CmdSize; ++ u8 *tlv = NULL; ++ MrvlIEtypes_sleep_param_t *sleep_tlv = NULL; ++ MrvlIEtypes_inact_sleep_param_t *inact_tlv = NULL; ++ u16 tlv_buf_left = 0; ++ MrvlIEtypesHeader_t *tlvbuf = NULL; ++ u16 tlv_type = 0; ++ u16 tlv_len = 0; ++ ++ ENTER(); ++ ++ /* Sanity check */ ++ if (req->ifr_data == NULL) { ++ PRINTM(ERROR, "uap_power_mode_ioctl() corrupt data\n"); ++ LEAVE(); ++ return -EFAULT; ++ } ++ ++ memset(&pm_cfg, 0, sizeof(ps_mgmt)); ++ if (copy_from_user(&pm_cfg, req->ifr_data, sizeof(ps_mgmt))) { ++ PRINTM(ERROR, "Copy from user failed\n"); ++ LEAVE(); ++ return -EFAULT; ++ } ++ PRINTM(CMND, ++ "ioctl power: flag=0x%x ps_mode=%d ctrl_bitmap=%d min_sleep=%d max_sleep=%d " ++ "inact_to=%d min_awake=%d max_awake=%d\n", pm_cfg.flags, ++ (int) pm_cfg.ps_mode, (int) pm_cfg.sleep_param.ctrl_bitmap, ++ (int) pm_cfg.sleep_param.min_sleep, ++ (int) pm_cfg.sleep_param.max_sleep, ++ (int) pm_cfg.inact_param.inactivity_to, ++ (int) pm_cfg.inact_param.min_awake, ++ (int) pm_cfg.inact_param.max_awake); ++ ++ if (pm_cfg. ++ flags & ~(PS_FLAG_PS_MODE | PS_FLAG_SLEEP_PARAM | ++ PS_FLAG_INACT_SLEEP_PARAM)) { ++ PRINTM(ERROR, "Invalid parameter: flags = 0x%x\n", pm_cfg.flags); ++ ret = -EINVAL; ++ goto done; ++ } ++ if (pm_cfg.ps_mode > PS_MODE_INACTIVITY) { ++ PRINTM(ERROR, "Invalid parameter: ps_mode = %d\n", (int) pm_cfg.flags); ++ ret = -EINVAL; ++ goto done; ++ } ++ ++ skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER); ++ if (!skb) { ++ PRINTM(INFO, "No free skb\n"); ++ ret = -ENOMEM; ++ goto done; ++ } ++ ++ CmdSize = S_DS_GEN + sizeof(HostCmd_DS_POWER_MGMT_EXT); ++ ++ cmd = (HostCmd_DS_COMMAND *) (skb->data + INTF_HEADER_LEN); ++ cmd->Command = uap_cpu_to_le16(HOST_CMD_POWER_MGMT_EXT); ++ if (!pm_cfg.flags) { ++ cmd->params.pm_cfg.action = uap_cpu_to_le16(ACTION_GET); ++ } else { ++ cmd->params.pm_cfg.action = uap_cpu_to_le16(ACTION_SET); ++ cmd->params.pm_cfg.power_mode = uap_cpu_to_le16(pm_cfg.ps_mode); ++ tlv = (u8 *) & cmd->params.pm_cfg + sizeof(HostCmd_DS_POWER_MGMT_EXT); ++ ++ if ((pm_cfg.ps_mode) && (pm_cfg.flags & PS_FLAG_SLEEP_PARAM)) { ++ sleep_tlv = (MrvlIEtypes_sleep_param_t *) tlv; ++ sleep_tlv->header.Type = uap_cpu_to_le16(TLV_TYPE_AP_SLEEP_PARAM); ++ sleep_tlv->header.Len = ++ uap_cpu_to_le16(sizeof(MrvlIEtypes_sleep_param_t) - ++ sizeof(MrvlIEtypesHeader_t)); ++ sleep_tlv->ctrl_bitmap = ++ uap_cpu_to_le32(pm_cfg.sleep_param.ctrl_bitmap); ++ sleep_tlv->min_sleep = ++ uap_cpu_to_le32(pm_cfg.sleep_param.min_sleep); ++ sleep_tlv->max_sleep = ++ uap_cpu_to_le32(pm_cfg.sleep_param.max_sleep); ++ CmdSize += sizeof(MrvlIEtypes_sleep_param_t); ++ tlv += sizeof(MrvlIEtypes_sleep_param_t); ++ } ++ if ((pm_cfg.ps_mode == PS_MODE_INACTIVITY) && ++ (pm_cfg.flags & PS_FLAG_INACT_SLEEP_PARAM)) { ++ inact_tlv = (MrvlIEtypes_inact_sleep_param_t *) tlv; ++ inact_tlv->header.Type = ++ uap_cpu_to_le16(TLV_TYPE_AP_INACT_SLEEP_PARAM); ++ inact_tlv->header.Len = ++ uap_cpu_to_le16(sizeof(MrvlIEtypes_inact_sleep_param_t) - ++ sizeof(MrvlIEtypesHeader_t)); ++ inact_tlv->inactivity_to = ++ uap_cpu_to_le32(pm_cfg.inact_param.inactivity_to); ++ inact_tlv->min_awake = ++ uap_cpu_to_le32(pm_cfg.inact_param.min_awake); ++ inact_tlv->max_awake = ++ uap_cpu_to_le32(pm_cfg.inact_param.max_awake); ++ CmdSize += sizeof(MrvlIEtypes_inact_sleep_param_t); ++ tlv += sizeof(MrvlIEtypes_inact_sleep_param_t); ++ } ++ } ++ cmd->Size = uap_cpu_to_le16(CmdSize); ++ skb_put(skb, CmdSize + INTF_HEADER_LEN); ++ if (UAP_STATUS_SUCCESS != ++ uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP)) { ++ PRINTM(ERROR, "Fail to process cmd POWER_MODE\n"); ++ ret = -EFAULT; ++ goto done; ++ } ++ if (!Adapter->CmdSize) { ++ PRINTM(ERROR, "Cmd Size is 0\n"); ++ ret = -EFAULT; ++ goto done; ++ } ++ cmd = (HostCmd_DS_COMMAND *) Adapter->CmdBuf; ++ cmd->Result = uap_le16_to_cpu(cmd->Result); ++ if (cmd->Result != UAP_STATUS_SUCCESS) { ++ PRINTM(ERROR, "HOST_CMD_APCMD_POWER_MODE fail=%x\n", cmd->Result); ++ ret = -EFAULT; ++ goto done; ++ } ++ if (pm_cfg.flags) { ++ Adapter->psmode = uap_le16_to_cpu(cmd->params.pm_cfg.power_mode); ++ } else { ++ pm_cfg.flags = PS_FLAG_PS_MODE; ++ pm_cfg.ps_mode = uap_le16_to_cpu(cmd->params.pm_cfg.power_mode); ++ tlv_buf_left = ++ cmd->Size - (sizeof(HostCmd_DS_POWER_MGMT_EXT) + S_DS_GEN); ++ tlvbuf = ++ (MrvlIEtypesHeader_t *) ((u8 *) & cmd->params.pm_cfg + ++ sizeof(HostCmd_DS_POWER_MGMT_EXT)); ++ while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) { ++ tlv_type = uap_le16_to_cpu(tlvbuf->Type); ++ tlv_len = uap_le16_to_cpu(tlvbuf->Len); ++ switch (tlv_type) { ++ case TLV_TYPE_AP_SLEEP_PARAM: ++ sleep_tlv = (MrvlIEtypes_sleep_param_t *) tlvbuf; ++ pm_cfg.flags |= PS_FLAG_SLEEP_PARAM; ++ pm_cfg.sleep_param.ctrl_bitmap = ++ uap_le32_to_cpu(sleep_tlv->ctrl_bitmap); ++ pm_cfg.sleep_param.min_sleep = ++ uap_le32_to_cpu(sleep_tlv->min_sleep); ++ pm_cfg.sleep_param.max_sleep = ++ uap_le32_to_cpu(sleep_tlv->max_sleep); ++ break; ++ case TLV_TYPE_AP_INACT_SLEEP_PARAM: ++ inact_tlv = (MrvlIEtypes_inact_sleep_param_t *) tlvbuf; ++ pm_cfg.flags |= PS_FLAG_INACT_SLEEP_PARAM; ++ pm_cfg.inact_param.inactivity_to = ++ uap_le32_to_cpu(inact_tlv->inactivity_to); ++ pm_cfg.inact_param.min_awake = ++ uap_le32_to_cpu(inact_tlv->min_awake); ++ pm_cfg.inact_param.max_awake = ++ uap_le32_to_cpu(inact_tlv->max_awake); ++ break; ++ } ++ tlv_buf_left -= tlv_len + sizeof(MrvlIEtypesHeader_t); ++ tlvbuf = ++ (MrvlIEtypesHeader_t *) ((u8 *) tlvbuf + tlv_len + ++ sizeof(MrvlIEtypesHeader_t)); ++ } ++ /* Copy to user */ ++ if (copy_to_user(req->ifr_data, &pm_cfg, sizeof(ps_mgmt))) { ++ PRINTM(ERROR, "Copy to user failed!\n"); ++ LEAVE(); ++ return -EFAULT; ++ } ++ } ++ done: ++ LEAVE(); ++ return ret; ++} ++ ++/** ++ * @brief This function send bss_stop command to firmware ++ * ++ * @param priv A pointer to uap_private structure ++ * @return UAP_STATUS_SUCCESS on success, otherwise failure code ++ */ ++static int ++uap_bss_stop(uap_private * priv) ++{ ++ int ret = UAP_STATUS_SUCCESS; ++ u32 CmdSize; ++ HostCmd_DS_GEN *cmd; ++ uap_adapter *Adapter = priv->adapter; ++ struct sk_buff *skb; ++ ENTER(); ++ if (Adapter->HardwareStatus != HWReady) { ++ PRINTM(ERROR, "uap_bss_stop:Hardware is not ready!\n"); ++ ret = -EFAULT; ++ goto done; ++ } ++ skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER); ++ if (!skb) { ++ PRINTM(ERROR, "No free skb\n"); ++ ret = -ENOMEM; ++ goto done; ++ } ++ CmdSize = sizeof(HostCmd_DS_GEN); ++ cmd = (HostCmd_DS_GEN *) (skb->data + INTF_HEADER_LEN); ++ cmd->Command = uap_cpu_to_le16(HOST_CMD_APCMD_BSS_STOP); ++ cmd->Size = uap_cpu_to_le16(CmdSize); ++ skb_put(skb, CmdSize + INTF_HEADER_LEN); ++ PRINTM(CMND, "APCMD_BSS_STOP\n"); ++ if (UAP_STATUS_SUCCESS != ++ uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP_TIMEOUT)) { ++ PRINTM(ERROR, "Fail to process cmd BSS_STOP\n"); ++ ret = -EFAULT; ++ goto done; ++ } ++ done: ++ LEAVE(); ++ return ret; ++} ++ ++/******************************************************** ++ Global Functions ++********************************************************/ ++/** ++ * @brief This function send soft_reset command to firmware ++ * ++ * @param priv A pointer to uap_private structure ++ * @return UAP_STATUS_SUCCESS on success, otherwise failure code ++ */ ++int ++uap_soft_reset(uap_private * priv) ++{ ++ int ret = UAP_STATUS_SUCCESS; ++ u32 CmdSize; ++ HostCmd_DS_GEN *cmd; ++ uap_adapter *Adapter = priv->adapter; ++ struct sk_buff *skb; ++ ENTER(); ++ ret = uap_bss_stop(priv); ++ if (ret != UAP_STATUS_SUCCESS) ++ goto done; ++ skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER); ++ if (!skb) { ++ PRINTM(ERROR, "No free skb\n"); ++ ret = -ENOMEM; ++ goto done; ++ } ++ CmdSize = sizeof(HostCmd_DS_GEN); ++ cmd = (HostCmd_DS_GEN *) (skb->data + INTF_HEADER_LEN); ++ cmd->Command = uap_cpu_to_le16(HOST_CMD_APCMD_SOFT_RESET); ++ cmd->Size = uap_cpu_to_le16(CmdSize); ++ skb_put(skb, CmdSize + INTF_HEADER_LEN); ++ PRINTM(CMND, "APCMD_SOFT_RESET\n"); ++ if (UAP_STATUS_SUCCESS != ++ uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORSEND)) { ++ PRINTM(ERROR, "Fail to process cmd SOFT_RESET\n"); ++ ret = -EFAULT; ++ goto done; ++ } ++ Adapter->SurpriseRemoved = TRUE; ++ /* delay to allow hardware complete reset */ ++ os_sched_timeout(5); ++ if (priv->MediaConnected == TRUE) { ++ os_stop_queue(priv); ++ os_carrier_off(priv); ++ priv->MediaConnected = FALSE; ++ } ++ Adapter->CmdSize = 0; ++ Adapter->CmdWaitQWoken = TRUE; ++ wake_up_interruptible(&Adapter->cmdwait_q); ++ skb_queue_purge(&priv->adapter->tx_queue); ++ skb_queue_purge(&priv->adapter->cmd_queue); ++ done: ++ LEAVE(); ++ return ret; ++} ++ ++/** ++ * @brief This function processes received packet and forwards it ++ * to kernel/upper layer ++ * ++ * @param priv A pointer to uap_private ++ * @param skb A pointer to skb which includes the received packet ++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE ++ */ ++int ++uap_process_rx_packet(uap_private * priv, struct sk_buff *skb) ++{ ++ int ret = UAP_STATUS_SUCCESS; ++ RxPD *pRxPD; ++ ENTER(); ++ priv->adapter->ps_state = PS_STATE_AWAKE; ++ pRxPD = (RxPD *) skb->data; ++ endian_convert_RxPD(pRxPD); ++ DBG_HEXDUMP(DAT_D, "Rx", skb->data, MIN(skb->len, DATA_DUMP_LEN)); ++ skb_pull(skb, pRxPD->RxPktOffset); ++ priv->stats.rx_packets++; ++ priv->stats.rx_bytes += skb->len; ++ os_upload_rx_packet(priv, skb); ++ LEAVE(); ++ return ret; ++} ++ ++/** ++ * @brief This function opens the network device ++ * ++ * @param dev A pointer to net_device structure ++ * @return UAP_STATUS_SUCCESS ++ */ ++static int ++uap_open(struct net_device *dev) ++{ ++ uap_private *priv = (uap_private *) (uap_private *) netdev_priv(dev); ++ uap_adapter *Adapter = priv->adapter; ++ int i = 0; ++ ++ ENTER(); ++ ++ /* On some systems the device open handler will be called before HW ready. */ ++ /* Use the following flag check and wait function to work around the issue. */ ++ while ((Adapter->HardwareStatus != HWReady) && ++ (i < MAX_WAIT_DEVICE_READY_COUNT)) { ++ i++; ++ os_sched_timeout(100); ++ } ++ if (i >= MAX_WAIT_DEVICE_READY_COUNT) { ++ PRINTM(FATAL, "HW not ready, uap_open() return failure\n"); ++ LEAVE(); ++ return UAP_STATUS_FAILURE; ++ } ++ ++ if (MODULE_GET == 0) ++ return UAP_STATUS_FAILURE; ++ ++ priv->open = TRUE; ++ if (priv->MediaConnected == TRUE) { ++ os_carrier_on(priv); ++ os_start_queue(priv); ++ } else { ++ os_stop_queue(priv); ++ os_carrier_off(priv); ++ } ++ LEAVE(); ++ return UAP_STATUS_SUCCESS; ++} ++ ++/** ++ * @brief This function closes the network device ++ * ++ * @param dev A pointer to net_device structure ++ * @return UAP_STATUS_SUCCESS ++ */ ++static int ++uap_close(struct net_device *dev) ++{ ++ uap_private *priv = (uap_private *) netdev_priv(dev); ++ ++ ENTER(); ++ skb_queue_purge(&priv->adapter->tx_queue); ++ os_stop_queue(priv); ++ os_carrier_off(priv); ++ ++ MODULE_PUT; ++ priv->open = FALSE; ++ LEAVE(); ++ return UAP_STATUS_SUCCESS; ++} ++ ++/** ++ * @brief This function returns the network statistics ++ * ++ * @param dev A pointer to uap_private structure ++ * @return A pointer to net_device_stats structure ++ */ ++static struct net_device_stats * ++uap_get_stats(struct net_device *dev) ++{ ++ uap_private *priv = (uap_private *) netdev_priv(dev); ++ ++ return &priv->stats; ++} ++ ++/** ++ * @brief This function sets the MAC address to firmware. ++ * ++ * @param dev A pointer to uap_private structure ++ * @param addr MAC address to set ++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE ++ */ ++static int ++uap_set_mac_address(struct net_device *dev, void *addr) ++{ ++ int ret = UAP_STATUS_SUCCESS; ++ uap_private *priv = (uap_private *) netdev_priv(dev); ++ struct sockaddr *pHwAddr = (struct sockaddr *) addr; ++ u32 CmdSize; ++ HostCmd_DS_COMMAND *cmd; ++ MrvlIEtypes_MacAddr_t *pMacAddrTlv; ++ uap_adapter *Adapter = priv->adapter; ++ struct sk_buff *skb; ++ ++ ENTER(); ++ ++ /* Dump MAC address */ ++ DBG_HEXDUMP(CMD_D, "Original MAC addr", dev->dev_addr, ETH_ALEN); ++ DBG_HEXDUMP(CMD_D, "New MAC addr", pHwAddr->sa_data, ETH_ALEN); ++ if (priv->open && (priv->MediaConnected == TRUE)) { ++ os_carrier_on(priv); ++ os_start_queue(priv); ++ } ++ skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER); ++ if (!skb) { ++ PRINTM(ERROR, "No free skb\n"); ++ LEAVE(); ++ return -ENOMEM; ++ } ++ CmdSize = ++ S_DS_GEN + sizeof(HostCmd_SYS_CONFIG) + sizeof(MrvlIEtypes_MacAddr_t); ++ cmd = (HostCmd_DS_COMMAND *) (skb->data + INTF_HEADER_LEN); ++ cmd->Command = uap_cpu_to_le16(HOST_CMD_APCMD_SYS_CONFIGURE); ++ cmd->Size = uap_cpu_to_le16(CmdSize); ++ cmd->params.sys_config.Action = uap_cpu_to_le16(ACTION_SET); ++ pMacAddrTlv = ++ (MrvlIEtypes_MacAddr_t *) ((u8 *) cmd + S_DS_GEN + ++ sizeof(HostCmd_SYS_CONFIG)); ++ pMacAddrTlv->Header.Type = uap_cpu_to_le16(MRVL_AP_MAC_ADDRESS_TLV_ID); ++ pMacAddrTlv->Header.Len = uap_cpu_to_le16(ETH_ALEN); ++ memcpy(pMacAddrTlv->ApMacAddr, pHwAddr->sa_data, ETH_ALEN); ++ skb_put(skb, CmdSize + INTF_HEADER_LEN); ++ PRINTM(CMND, "set_mac_address\n"); ++ if (UAP_STATUS_SUCCESS != ++ uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP_TIMEOUT)) { ++ PRINTM(ERROR, "Fail to set mac address\n"); ++ LEAVE(); ++ return -EFAULT; ++ } ++ if (!Adapter->CmdSize) { ++ PRINTM(ERROR, "Cmd Size is 0\n"); ++ LEAVE(); ++ return -EFAULT; ++ } ++ cmd = (HostCmd_DS_COMMAND *) Adapter->CmdBuf; ++ cmd->Result = uap_cpu_to_le16(cmd->Result); ++ if (cmd->Result != UAP_STATUS_SUCCESS) { ++ PRINTM(ERROR, "set mac addrress fail,cmd result=%x\n", cmd->Result); ++ ret = -EFAULT; ++ } else ++ memcpy(dev->dev_addr, pHwAddr->sa_data, ETH_ALEN); ++ LEAVE(); ++ return ret; ++} ++ ++/** ++ * @brief This function sets multicast addresses to firmware ++ * ++ * @param dev A pointer to net_device structure ++ * @return n/a ++ */ ++static void ++uap_set_multicast_list(struct net_device *dev) ++{ ++ ENTER(); ++#warning uap_set_multicast_list not implemented. Expect problems with IPv6. ++ LEAVE(); ++} ++ ++/** ++ * @brief This function handles the timeout of packet ++ * transmission ++ * ++ * @param dev A pointer to net_device structure ++ * @return n/a ++ */ ++static void ++uap_tx_timeout(struct net_device *dev) ++{ ++ uap_private *priv = (uap_private *) netdev_priv(dev); ++ ++ ENTER(); ++ ++ PRINTM(DATA, "Tx timeout\n"); ++ UpdateTransStart(dev); ++ priv->num_tx_timeout++; ++ priv->adapter->IntCounter++; ++ wake_up_interruptible(&priv->MainThread.waitQ); ++ ++ LEAVE(); ++} ++ ++/** ++ * @brief This function handles packet transmission ++ * ++ * @param skb A pointer to sk_buff structure ++ * @param dev A pointer to net_device structure ++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE ++ */ ++static int ++uap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) ++{ ++ uap_private *priv = (uap_private *) netdev_priv(dev); ++ int ret = UAP_STATUS_SUCCESS; ++ ++ ENTER(); ++ PRINTM(DATA, "Data <= kernel\n"); ++ DBG_HEXDUMP(DAT_D, "Tx", skb->data, MIN(skb->len, DATA_DUMP_LEN)); ++ /* skb sanity check */ ++ if (!skb->len || (skb->len > MRVDRV_MAXIMUM_ETH_PACKET_SIZE)) { ++ PRINTM(ERROR, "Tx Error: Bad skb length %d : %d\n", skb->len, ++ MRVDRV_MAXIMUM_ETH_PACKET_SIZE); ++ priv->stats.tx_dropped++; ++ kfree(skb); ++ goto done; ++ } ++ skb_queue_tail(&priv->adapter->tx_queue, skb); ++ wake_up_interruptible(&priv->MainThread.waitQ); ++ if (skb_queue_len(&priv->adapter->tx_queue) > TX_HIGH_WATERMARK) { ++ UpdateTransStart(dev); ++ os_stop_queue(priv); ++ } ++ done: ++ LEAVE(); ++ return ret; ++} ++ ++/** ++ * @brief ioctl function - entry point ++ * ++ * @param dev A pointer to net_device structure ++ * @param req A pointer to ifreq structure ++ * @param cmd command ++ * @return UAP_STATUS_SUCCESS--success, otherwise fail ++ */ ++static int ++uap_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd) ++{ ++ int ret = UAP_STATUS_SUCCESS; ++ ++ ENTER(); ++ ++ PRINTM(CMND, "uap_do_ioctl: ioctl cmd = 0x%x\n", cmd); ++ ++ switch (cmd) { ++ case UAPHOSTCMD: ++ ret = uap_hostcmd_ioctl(dev, req); ++ break; ++ case UAP_POWER_MODE: ++ ret = uap_power_mode_ioctl(dev, req); ++ break; ++ default: ++ ret = -EINVAL; ++ break; ++ } ++ ++ LEAVE(); ++ return ret; ++} ++ ++/** ++ * @brief This function handles events generated by firmware ++ * ++ * @param priv A pointer to uap_private structure ++ * @param payload A pointer to payload buffer ++ * @param len Length of the payload ++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE ++ */ ++int ++uap_process_event(uap_private * priv, u8 * payload, uint len) ++{ ++ int ret = UAP_STATUS_SUCCESS; ++ uap_adapter *Adapter = priv->adapter; ++ struct sk_buff *skb = NULL; ++ struct nlmsghdr *nlh = NULL; ++ struct sock *sk = Adapter->nl_sk; ++ AP_Event *pEvent; ++ ++ ENTER(); ++ Adapter->ps_state = PS_STATE_AWAKE; ++ if (len > NL_MAX_PAYLOAD) { ++ PRINTM(ERROR, "event size is too big!!! len=%d\n", len); ++ ret = UAP_STATUS_FAILURE; ++ goto done; ++ } ++ pEvent = (AP_Event *) payload; ++ PRINTM(CMND, "Event: %d\n", pEvent->EventId); ++ switch (pEvent->EventId) { ++ case MICRO_AP_EV_ID_BSS_START: ++ memcpy(priv->uap_dev.netdev->dev_addr, pEvent->MacAddr, ETH_ALEN); ++ DBG_HEXDUMP(CMD_D, "BSS MAC addr", priv->uap_dev.netdev->dev_addr, ++ ETH_ALEN); ++ break; ++ case MICRO_AP_EV_BSS_ACTIVE: ++ // carrier on ++ priv->MediaConnected = TRUE; ++ os_carrier_on(priv); ++ os_start_queue(priv); ++ break; ++ case MICRO_AP_EV_BSS_IDLE: ++ os_stop_queue(priv); ++ os_carrier_off(priv); ++ priv->MediaConnected = FALSE; ++ break; ++ case EVENT_PS_AWAKE: ++ PRINTM(CMND, "UAP: PS_AWAKE\n"); ++ Adapter->ps_state = PS_STATE_AWAKE; ++ Adapter->WakeupTries = 0; ++ break; ++ case EVENT_PS_SLEEP: ++ PRINTM(CMND, "UAP: PS_SLEEP\n"); ++ Adapter->ps_state = PS_STATE_PRE_SLEEP; ++ break; ++ default: ++ break; ++ } ++ if ((pEvent->EventId == EVENT_PS_AWAKE) || ++ (pEvent->EventId == EVENT_PS_SLEEP)) ++ goto done; ++ if (sk) { ++ /* Allocate skb */ ++ if (!(skb = alloc_skb(NLMSG_SPACE(NL_MAX_PAYLOAD), GFP_ATOMIC))) { ++ PRINTM(ERROR, "Could not allocate skb for netlink.\n"); ++ ret = UAP_STATUS_FAILURE; ++ goto done; ++ } ++ nlh = (struct nlmsghdr *) skb->data; ++ nlh->nlmsg_len = NLMSG_SPACE(len); ++ ++ /* From kernel */ ++ nlh->nlmsg_pid = 0; ++ nlh->nlmsg_flags = 0; ++ ++ /* Data */ ++ skb_put(skb, nlh->nlmsg_len); ++ memcpy(NLMSG_DATA(nlh), payload, len); ++ ++ /* From Kernel */ ++ NETLINK_CB(skb).pid = 0; ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++ /* Multicast message */ ++ NETLINK_CB(skb).dst_pid = 0; ++#endif ++ ++ /* Multicast group number */ ++ NETLINK_CB(skb).dst_group = NL_MULTICAST_GROUP; ++ ++ /* Send message */ ++ netlink_broadcast(sk, skb, 0, NL_MULTICAST_GROUP, GFP_KERNEL); ++ ++ ret = UAP_STATUS_SUCCESS; ++ } else { ++ PRINTM(ERROR, "Could not send event through NETLINK. Link down.\n"); ++ ret = UAP_STATUS_FAILURE; ++ } ++ done: ++ LEAVE(); ++ return ret; ++} ++ ++/** ++ * @brief This function handles the interrupt. it will change PS ++ * state if applicable. it will wake up main_thread to handle ++ * the interrupt event as well. ++ * ++ * @param priv A pointer to uap_private structure ++ * @return n/a ++ */ ++void ++uap_interrupt(uap_private * priv) ++{ ++ ENTER(); ++ priv->adapter->IntCounter++; ++ priv->adapter->WakeupTries = 0; ++ PRINTM(INFO, "*\n"); ++ wake_up_interruptible(&priv->MainThread.waitQ); ++ ++ LEAVE(); ++ ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) ++/** Network device handlers */ ++static const struct net_device_ops uap_netdev_ops = { ++ .ndo_open = uap_open, ++ .ndo_start_xmit = uap_hard_start_xmit, ++ .ndo_stop = uap_close, ++ .ndo_do_ioctl = uap_do_ioctl, ++ .ndo_set_mac_address = uap_set_mac_address, ++ .ndo_tx_timeout = uap_tx_timeout, ++ .ndo_get_stats = uap_get_stats, ++ .ndo_set_multicast_list = uap_set_multicast_list, ++}; ++#endif ++ ++/** ++ * @brief This function adds the card. it will probe the ++ * card, allocate the uap_priv and initialize the device. ++ * ++ * @param card A pointer to card ++ * @return A pointer to uap_private structure ++ */ ++uap_private * ++uap_add_card(void *card) ++{ ++ struct net_device *dev = NULL; ++ uap_private *priv = NULL; ++ ++ ENTER(); ++ ++ if (OS_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem)) ++ goto exit_sem_err; ++ ++ /* Allocate an Ethernet device */ ++ if (!(dev = alloc_etherdev(sizeof(uap_private)))) { ++ PRINTM(FATAL, "Init ethernet device failed!\n"); ++ goto error; ++ } ++ priv = (uap_private *) netdev_priv(dev); ++ ++ /* Allocate name */ ++ if (dev_alloc_name(dev, "uap%d") < 0) { ++ PRINTM(ERROR, "Could not allocate device name!\n"); ++ goto error; ++ } ++ ++ /* Allocate buffer for uap_adapter */ ++ if (!(priv->adapter = kmalloc(sizeof(uap_adapter), GFP_KERNEL))) { ++ PRINTM(FATAL, "Allocate buffer for uap_adapter failed!\n"); ++ goto error; ++ } ++ memset(priv->adapter, 0, sizeof(uap_adapter)); ++ ++ priv->uap_dev.netdev = dev; ++ priv->uap_dev.card = card; ++ priv->MediaConnected = FALSE; ++ uappriv = priv; ++ ((struct sdio_mmc_card *) card)->priv = priv; ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) ++ SET_MODULE_OWNER(dev); ++#endif ++ ++ /* Setup the OS Interface to our functions */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) ++ dev->open = uap_open; ++ dev->stop = uap_close; ++ dev->hard_start_xmit = uap_hard_start_xmit; ++ dev->tx_timeout = uap_tx_timeout; ++ dev->get_stats = uap_get_stats; ++ dev->do_ioctl = uap_do_ioctl; ++ dev->set_mac_address = uap_set_mac_address; ++ dev->set_multicast_list = uap_set_multicast_list; ++#else ++ dev->netdev_ops = &uap_netdev_ops; ++#endif ++ dev->watchdog_timeo = MRVDRV_DEFAULT_WATCHDOG_TIMEOUT; ++ dev->hard_header_len += sizeof(TxPD) + INTF_HEADER_LEN; ++ dev->hard_header_len += HEADER_ALIGNMENT; ++#define NETIF_F_DYNALLOC 16 ++ dev->features |= NETIF_F_DYNALLOC; ++ dev->flags |= IFF_BROADCAST | IFF_MULTICAST; ++ ++ /* Init SW */ ++ if (uap_init_sw(priv)) { ++ PRINTM(FATAL, "Software Init Failed\n"); ++ goto error; ++ } ++ ++ PRINTM(INFO, "Starting kthread...\n"); ++ priv->MainThread.priv = priv; ++ spin_lock_init(&priv->driver_lock); ++ uap_create_thread(uap_service_main_thread, &priv->MainThread, ++ "uap_main_service"); ++ while (priv->MainThread.pid == 0) { ++ os_sched_timeout(2); ++ } ++ ++ /* Register the device */ ++ if (sbi_register_dev(priv) < 0) { ++ PRINTM(FATAL, "Failed to register uap device!\n"); ++ goto err_registerdev; ++ } ++#ifdef FW_DNLD_NEEDED ++ SET_NETDEV_DEV(dev, priv->hotplug_device); ++#endif ++ ++ /* Init FW and HW */ ++ if (uap_init_fw(priv)) { ++ PRINTM(FATAL, "Firmware Init Failed\n"); ++ goto err_init_fw; ++ } ++ ++ priv->uap_dev.cmd_sent = FALSE; ++ priv->uap_dev.data_sent = FALSE; ++ ++ /* Get mac address from firmware */ ++ if (uap_get_mac_address(priv)) { ++ PRINTM(FATAL, "Fail to get mac address\n"); ++ goto err_init_fw; ++ } ++ /* Register network device */ ++ if (register_netdev(dev)) { ++ printk(KERN_ERR "Cannot register network device!\n"); ++ goto err_init_fw; ++ } ++#ifdef CONFIG_PROC_FS ++ uap_proc_entry(priv, dev); ++ uap_debug_entry(priv, dev); ++#endif /* CPNFIG_PROC_FS */ ++ OS_REL_SEMAPHORE(&AddRemoveCardSem); ++ ++ LEAVE(); ++ return priv; ++ err_init_fw: ++ sbi_unregister_dev(priv); ++ err_registerdev: ++ ((struct sdio_mmc_card *) card)->priv = NULL; ++ /* Stop the thread servicing the interrupts */ ++ priv->adapter->SurpriseRemoved = TRUE; ++ wake_up_interruptible(&priv->MainThread.waitQ); ++ while (priv->MainThread.pid) { ++ os_sched_timeout(1); ++ } ++ error: ++ if (dev) { ++ if (dev->reg_state == NETREG_REGISTERED) ++ unregister_netdev(dev); ++ if (priv->adapter) ++ uap_free_adapter(priv); ++ free_netdev(dev); ++ uappriv = NULL; ++ } ++ OS_REL_SEMAPHORE(&AddRemoveCardSem); ++ exit_sem_err: ++ LEAVE(); ++ return NULL; ++} ++ ++/** ++ * @brief This function removes the card. ++ * ++ * @param card A pointer to card ++ * @return UAP_STATUS_SUCCESS ++ */ ++int ++uap_remove_card(void *card) ++{ ++ uap_private *priv = uappriv; ++ uap_adapter *Adapter; ++ struct net_device *dev; ++ ++ ENTER(); ++ ++ if (OS_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem)) ++ goto exit_sem_err; ++ ++ if (!priv || !(Adapter = priv->adapter)) { ++ goto exit_remove; ++ } ++ Adapter->SurpriseRemoved = TRUE; ++ if (Adapter->cmd_pending == TRUE) { ++ /* Wake up cmd Q */ ++ Adapter->CmdWaitQWoken = TRUE; ++ wake_up_interruptible(&Adapter->cmdwait_q); ++ } ++ dev = priv->uap_dev.netdev; ++ if (priv->MediaConnected == TRUE) { ++ os_stop_queue(priv); ++ os_carrier_off(priv); ++ priv->MediaConnected = FALSE; ++ } ++ Adapter->CmdSize = 0; ++ Adapter->CmdWaitQWoken = TRUE; ++ wake_up_interruptible(&Adapter->cmdwait_q); ++ skb_queue_purge(&priv->adapter->tx_queue); ++ skb_queue_purge(&priv->adapter->cmd_queue); ++ ++ /* Disable interrupts on the card */ ++ sbi_disable_host_int(priv); ++ PRINTM(INFO, "netdev_finish_unregister: %s%s.\n", dev->name, ++ (dev->features & NETIF_F_DYNALLOC) ? "" : ", old style"); ++ unregister_netdev(dev); ++ PRINTM(INFO, "Unregister finish\n"); ++ wake_up_interruptible(&priv->MainThread.waitQ); ++ while (priv->MainThread.pid) { ++ os_sched_timeout(1); ++ } ++ ++ if ((Adapter->nl_sk) && ((Adapter->nl_sk)->sk_socket)) { ++ sock_release((Adapter->nl_sk)->sk_socket); ++ Adapter->nl_sk = NULL; ++ } ++#ifdef CONFIG_PROC_FS ++ uap_debug_remove(priv); ++ uap_proc_remove(priv); ++#endif ++ sbi_unregister_dev(priv); ++ PRINTM(INFO, "Free Adapter\n"); ++ uap_free_adapter(priv); ++ priv->uap_dev.netdev = NULL; ++ free_netdev(dev); ++ uappriv = NULL; ++ ++ exit_remove: ++ OS_REL_SEMAPHORE(&AddRemoveCardSem); ++ exit_sem_err: ++ LEAVE(); ++ return UAP_STATUS_SUCCESS; ++} ++ ++/** ++ * @brief This function initializes module. ++ * ++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE ++ */ ++static int __init ++uap_init_module(void) ++{ ++ int ret = UAP_STATUS_SUCCESS; ++ ENTER(); ++ ++ OS_INIT_SEMAPHORE(&AddRemoveCardSem); ++ ret = sbi_register(); ++ LEAVE(); ++ return ret; ++} ++ ++/** ++ * @brief This function cleans module ++ * ++ * @return n/a ++ */ ++static void __exit ++uap_cleanup_module(void) ++{ ++ ENTER(); ++ ++ if (OS_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem)) ++ goto exit_sem_err; ++ ++ if ((uappriv) && (uappriv->adapter)) { ++ uap_func_shutdown(uappriv); ++ } ++ OS_REL_SEMAPHORE(&AddRemoveCardSem); ++ exit_sem_err: ++ sbi_unregister(); ++ LEAVE(); ++} ++ ++module_init(uap_init_module); ++module_exit(uap_cleanup_module); ++module_param(helper_name, charp, 0); ++MODULE_PARM_DESC(helper_name, "Helper name"); ++module_param(fw_name, charp, 0); ++MODULE_PARM_DESC(fw_name, "Firmware name"); ++ ++MODULE_DESCRIPTION("M-UAP Driver"); ++MODULE_AUTHOR("Marvell International Ltd."); ++MODULE_VERSION(DRIVER_VERSION); ++MODULE_LICENSE("GPL"); +diff -Naupr linux-2.6.37/drivers/net/wireless/libertas_uap/uap_proc.c linux-2.6.37-new/drivers/net/wireless/libertas_uap/uap_proc.c +--- linux-2.6.37/drivers/net/wireless/libertas_uap/uap_proc.c 1969-12-31 17:00:00.000000000 -0700 ++++ linux-2.6.37-new/drivers/net/wireless/libertas_uap/uap_proc.c 2011-01-08 06:01:04.050835055 -0700 +@@ -0,0 +1,296 @@ ++/** @file uap_proc.c ++ * @brief This file contains functions for proc file. ++ * ++ * Copyright (C) 2008-2009, Marvell International Ltd. ++ * ++ * This software file (the "File") is distributed by Marvell International ++ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 ++ * (the "License"). You may use, redistribute and/or modify this File in ++ * accordance with the terms and conditions of the License, a copy of which ++ * is available along with the File in the gpl.txt file or by writing to ++ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. ++ * ++ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ++ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about ++ * this warranty disclaimer. ++ * ++ */ ++#ifdef CONFIG_PROC_FS ++#include "uap_headers.h" ++ ++/** /proc directory root */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) ++#define PROC_DIR NULL ++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) ++#define PROC_DIR &proc_root ++#else ++#define PROC_DIR proc_net ++#endif ++ ++/******************************************************** ++ Local Variables ++********************************************************/ ++ ++/******************************************************** ++ Global Variables ++********************************************************/ ++ ++/******************************************************** ++ Local Functions ++********************************************************/ ++ ++/** ++ * @brief proc read function ++ * ++ * @param page pointer to buffer ++ * @param start read data starting position ++ * @param offset offset ++ * @param count counter ++ * @param eof end of file flag ++ * @param data data to output ++ * @return number of output data ++ */ ++static int ++uap_proc_read(char *page, char **start, off_t offset, ++ int count, int *eof, void *data) ++{ ++ int i; ++ char *p = page; ++ struct net_device *netdev = data; ++ struct netdev_hw_addr *ha; ++ char fmt[64]; ++ uap_private *priv = (uap_private *) netdev_priv(netdev); ++ ++ if (offset != 0) { ++ *eof = 1; ++ goto exit; ++ } ++ ++ strcpy(fmt, DRIVER_VERSION); ++ ++ p += sprintf(p, "driver_name = " "\"uap\"\n"); ++ p += sprintf(p, "driver_version = %s-(FP%s)", fmt, FPNUM); ++ p += sprintf(p, "\nInterfaceName=\"%s\"\n", netdev->name); ++ p += sprintf(p, "State=\"%s\"\n", ++ ((priv->MediaConnected == ++ FALSE) ? "Disconnected" : "Connected")); ++ p += sprintf(p, "MACAddress=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n", ++ netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2], ++ netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]); ++ i = 0; ++ netdev_for_each_mc_addr(ha, netdev) { ++ ++i; ++ } ++ p += sprintf(p, "MCCount=\"%d\"\n", i); ++ ++ /* ++ * Put out the multicast list ++ */ ++ i = 0; ++ netdev_for_each_mc_addr(ha, netdev) { ++ p += sprintf(p, ++ "MCAddr[%d]=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n", ++ i++, ++ ha->addr[0], ha->addr[1], ++ ha->addr[2], ha->addr[3], ++ ha->addr[4], ha->addr[5]); ++ } ++ ++ p += sprintf(p, "num_tx_bytes = %lu\n", priv->stats.tx_bytes); ++ p += sprintf(p, "num_rx_bytes = %lu\n", priv->stats.rx_bytes); ++ p += sprintf(p, "num_tx_pkts = %lu\n", priv->stats.tx_packets); ++ p += sprintf(p, "num_rx_pkts = %lu\n", priv->stats.rx_packets); ++ p += sprintf(p, "num_tx_pkts_dropped = %lu\n", priv->stats.tx_dropped); ++ p += sprintf(p, "num_rx_pkts_dropped = %lu\n", priv->stats.rx_dropped); ++ p += sprintf(p, "num_tx_pkts_err = %lu\n", priv->stats.tx_errors); ++ p += sprintf(p, "num_rx_pkts_err = %lu\n", priv->stats.rx_errors); ++ p += sprintf(p, "num_tx_timeout = %u\n", priv->num_tx_timeout); ++ p += sprintf(p, "carrier %s\n", ++ ((netif_carrier_ok(priv->uap_dev.netdev)) ? "on" : "off")); ++ p += sprintf(p, "tx queue %s\n", ++ ((netif_queue_stopped(priv->uap_dev.netdev)) ? "stopped" : ++ "started")); ++ ++ exit: ++ return (p - page); ++} ++ ++/** ++ * @brief hwstatus proc write function ++ * ++ * @param f file pointer ++ * @param buf pointer to data buffer ++ * @param cnt data number to write ++ * @param data data to write ++ * @return number of data ++ */ ++static int ++uap_hwstatus_write(struct file *f, const char *buf, unsigned long cnt, ++ void *data) ++{ ++ struct net_device *netdev = data; ++ uap_private *priv = (uap_private *) netdev_priv(netdev); ++ char databuf[10]; ++ int hwstatus; ++ MODULE_GET; ++ if (cnt > 10) { ++ MODULE_PUT; ++ return cnt; ++ } ++ if (copy_from_user(databuf, buf, cnt)) { ++ MODULE_PUT; ++ return 0; ++ } ++ hwstatus = string_to_number(databuf); ++ switch (hwstatus) { ++ case HWReset: ++ PRINTM(MSG, "reset hw\n"); ++ uap_soft_reset(priv); ++ priv->adapter->HardwareStatus = HWReset; ++ break; ++ default: ++ break; ++ } ++ MODULE_PUT; ++ return cnt; ++} ++ ++/** ++ * @brief hwstatus proc read function ++ * ++ * @param page pointer to buffer ++ * @param s read data starting position ++ * @param off offset ++ * @param cnt counter ++ * @param eof end of file flag ++ * @param data data to output ++ * @return number of output data ++ */ ++static int ++uap_hwstatus_read(char *page, char **s, off_t off, int cnt, int *eof, ++ void *data) ++{ ++ char *p = page; ++ struct net_device *netdev = data; ++ uap_private *priv = (uap_private *) netdev_priv(netdev); ++ MODULE_GET; ++ p += sprintf(p, "%d\n", priv->adapter->HardwareStatus); ++ MODULE_PUT; ++ return p - page; ++} ++ ++/******************************************************** ++ Global Functions ++********************************************************/ ++/** ++ * @brief create uap proc file ++ * ++ * @param priv pointer uap_private ++ * @param dev pointer net_device ++ * @return N/A ++ */ ++void ++uap_proc_entry(uap_private * priv, struct net_device *dev) ++{ ++ struct proc_dir_entry *r = PROC_DIR; ++ ++ PRINTM(INFO, "Creating Proc Interface\n"); ++ /* Check if uap directory already exists */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) ++ for (r = r->subdir; r; r = r->next) { ++ if (r->namelen && !strcmp("uap", r->name)) { ++ /* Directory exists */ ++ PRINTM(WARN, "proc directory already exists!\n"); ++ priv->proc_uap = r; ++ break; ++ } ++ } ++#endif ++ if (!priv->proc_uap) { ++ priv->proc_uap = proc_mkdir("uap", PROC_DIR); ++ if (!priv->proc_uap) ++ return; ++ else ++ atomic_set(&priv->proc_uap->count, 1); ++ } else { ++ atomic_inc(&priv->proc_uap->count); ++ } ++ priv->proc_entry = proc_mkdir(dev->name, priv->proc_uap); ++ ++ if (priv->proc_entry) { ++ r = create_proc_read_entry("info", 0, priv->proc_entry, uap_proc_read, ++ dev); ++ r = create_proc_entry("hwstatus", 0644, priv->proc_entry); ++ if (r) { ++ r->data = dev; ++ r->read_proc = uap_hwstatus_read; ++ r->write_proc = uap_hwstatus_write; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) ++ r->owner = THIS_MODULE; ++#endif ++ } else ++ PRINTM(MSG, "Fail to create proc hwstatus\n"); ++ } ++} ++ ++/** ++ * @brief remove proc file ++ * ++ * @param priv pointer uap_private ++ * @return N/A ++ */ ++void ++uap_proc_remove(uap_private * priv) ++{ ++ if (priv->proc_uap) { ++ if (priv->proc_entry) { ++ remove_proc_entry("info", priv->proc_entry); ++ remove_proc_entry("hwstatus", priv->proc_entry); ++ } ++ remove_proc_entry(priv->uap_dev.netdev->name, priv->proc_uap); ++ atomic_dec(&priv->proc_uap->count); ++ if (atomic_read(&(priv->proc_uap->count)) == 0) ++ remove_proc_entry("uap", PROC_DIR); ++ } ++} ++ ++/** ++ * @brief convert string to number ++ * ++ * @param s pointer to numbered string ++ * @return converted number from string s ++ */ ++int ++string_to_number(char *s) ++{ ++ int r = 0; ++ int base = 0; ++ int pn = 1; ++ ++ if (strncmp(s, "-", 1) == 0) { ++ pn = -1; ++ s++; ++ } ++ if ((strncmp(s, "0x", 2) == 0) || (strncmp(s, "0X", 2) == 0)) { ++ base = 16; ++ s += 2; ++ } else ++ base = 10; ++ ++ for (s = s; *s != 0; s++) { ++ if ((*s >= '0') && (*s <= '9')) ++ r = (r * base) + (*s - '0'); ++ else if ((*s >= 'A') && (*s <= 'F')) ++ r = (r * base) + (*s - 'A' + 10); ++ else if ((*s >= 'a') && (*s <= 'f')) ++ r = (r * base) + (*s - 'a' + 10); ++ else ++ break; ++ } ++ ++ return (r * pn); ++} ++ ++#endif +diff -Naupr linux-2.6.37/drivers/net/wireless/libertas_uap/uap_sdio_mmc.c linux-2.6.37-new/drivers/net/wireless/libertas_uap/uap_sdio_mmc.c +--- linux-2.6.37/drivers/net/wireless/libertas_uap/uap_sdio_mmc.c 1969-12-31 17:00:00.000000000 -0700 ++++ linux-2.6.37-new/drivers/net/wireless/libertas_uap/uap_sdio_mmc.c 2011-01-08 06:01:04.055834709 -0700 +@@ -0,0 +1,1428 @@ ++/** @file uap_sdio_mmc.c ++ * @brief This file contains SDIO IF (interface) module ++ * related functions. ++ * ++ * Copyright (C) 2007-2009, Marvell International Ltd. ++ * ++ * This software file (the "File") is distributed by Marvell International ++ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 ++ * (the "License"). You may use, redistribute and/or modify this File in ++ * accordance with the terms and conditions of the License, a copy of which ++ * is available along with the File in the gpl.txt file or by writing to ++ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. ++ * ++ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ++ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about ++ * this warranty disclaimer. ++ * ++ */ ++/**************************************************** ++Change log: ++****************************************************/ ++ ++#include "uap_sdio_mmc.h" ++ ++#include ++ ++/** define SDIO block size */ ++/* We support up to 480-byte block size due to FW buffer limitation. */ ++#define SD_BLOCK_SIZE 256 ++ ++/** define allocated buffer size */ ++#define ALLOC_BUF_SIZE (((MAX(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, \ ++ MRVDRV_SIZE_OF_CMD_BUFFER) + INTF_HEADER_LEN \ ++ + SD_BLOCK_SIZE - 1) / SD_BLOCK_SIZE) * SD_BLOCK_SIZE) ++ ++/** Max retry number of CMD53 write */ ++#define MAX_WRITE_IOMEM_RETRY 2 ++ ++/******************************************************** ++ Local Variables ++********************************************************/ ++ ++/** SDIO Rx unit */ ++static u8 sdio_rx_unit = 0; ++ ++/**Interrupt status */ ++static u8 sd_ireg = 0; ++/******************************************************** ++ Global Variables ++********************************************************/ ++extern u8 *helper_name; ++extern u8 *fw_name; ++/** Default helper name */ ++#define DEFAULT_HELPER_NAME "mrvl/helper_sd.bin" ++/** Default firmware name */ ++#define DEFAULT_FW_NAME "mrvl/sd8688_ap.bin" ++ ++/******************************************************** ++ Local Functions ++********************************************************/ ++/** ++ * @brief This function reads the IO register. ++ * ++ * @param priv A pointer to uap_private structure ++ * @param reg register to be read ++ * @param dat A pointer to variable that keeps returned value ++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE ++ */ ++static int ++sbi_read_ioreg(uap_private * priv, u32 reg, u8 * dat) ++{ ++ struct sdio_mmc_card *card; ++ int ret = UAP_STATUS_FAILURE; ++ ++ ENTER(); ++ ++ card = priv->uap_dev.card; ++ if (!card || !card->func) { ++ PRINTM(ERROR, "sbi_read_ioreg(): card or function is NULL!\n"); ++ goto done; ++ } ++ ++ *dat = sdio_readb(card->func, reg, &ret); ++ if (ret) { ++ PRINTM(ERROR, "sbi_read_ioreg(): sdio_readb failed! ret=%d\n", ret); ++ goto done; ++ } ++ ++ PRINTM(INFO, "sbi_read_ioreg() priv=%p func=%d reg=%#x dat=%#x\n", priv, ++ card->func->num, reg, *dat); ++ ++ done: ++ LEAVE(); ++ return ret; ++} ++ ++/** ++ * @brief This function writes the IO register. ++ * ++ * @param priv A pointer to uap_private structure ++ * @param reg register to be written ++ * @param dat the value to be written ++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE ++ */ ++static int ++sbi_write_ioreg(uap_private * priv, u32 reg, u8 dat) ++{ ++ struct sdio_mmc_card *card; ++ int ret = UAP_STATUS_FAILURE; ++ ++ ENTER(); ++ ++ card = priv->uap_dev.card; ++ if (!card || !card->func) { ++ PRINTM(ERROR, "sbi_write_ioreg(): card or function is NULL!\n"); ++ goto done; ++ } ++ ++ PRINTM(INFO, "sbi_write_ioreg() priv=%p func=%d reg=%#x dat=%#x\n", priv, ++ card->func->num, reg, dat); ++ ++ sdio_writeb(card->func, dat, reg, &ret); ++ if (ret) { ++ PRINTM(ERROR, "sbi_write_ioreg(): sdio_readb failed! ret=%d\n", ret); ++ goto done; ++ } ++ ++ done: ++ LEAVE(); ++ return ret; ++} ++ ++/** ++ * @brief This function get rx_unit value ++ * ++ * @param priv A pointer to uap_private structure ++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE ++ */ ++static int ++sd_get_rx_unit(uap_private * priv) ++{ ++ int ret = UAP_STATUS_SUCCESS; ++ u8 reg; ++ ++ ENTER(); ++ ++ ret = sbi_read_ioreg(priv, CARD_RX_UNIT_REG, ®); ++ if (ret == UAP_STATUS_SUCCESS) ++ sdio_rx_unit = reg; ++ ++ LEAVE(); ++ return ret; ++} ++ ++/** ++ * @brief This function reads rx length ++ * ++ * @param priv A pointer to uap_private structure ++ * @param dat A pointer to keep returned data ++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE ++ */ ++static int ++sd_read_rx_len(uap_private * priv, u16 * dat) ++{ ++ int ret = UAP_STATUS_SUCCESS; ++ u8 reg; ++ ++ ENTER(); ++ ++ ret = sbi_read_ioreg(priv, CARD_RX_LEN_REG, ®); ++ if (ret == UAP_STATUS_SUCCESS) ++ *dat = (u16) reg << sdio_rx_unit; ++ ++ LEAVE(); ++ return ret; ++} ++ ++/** ++ * @brief This function reads fw status registers ++ * ++ * @param priv A pointer to uap_private structure ++ * @param dat A pointer to keep returned data ++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE ++ */ ++static int ++sd_read_firmware_status(uap_private * priv, u16 * dat) ++{ ++ int ret = UAP_STATUS_SUCCESS; ++ u8 fws0; ++ u8 fws1; ++ ++ ENTER(); ++ ++ ret = sbi_read_ioreg(priv, CARD_FW_STATUS0_REG, &fws0); ++ if (ret < 0) { ++ LEAVE(); ++ return UAP_STATUS_FAILURE; ++ } ++ ++ ret = sbi_read_ioreg(priv, CARD_FW_STATUS1_REG, &fws1); ++ if (ret < 0) { ++ LEAVE(); ++ return UAP_STATUS_FAILURE; ++ } ++ ++ *dat = (((u16) fws1) << 8) | fws0; ++ ++ LEAVE(); ++ return UAP_STATUS_SUCCESS; ++} ++ ++/** ++ * @brief This function polls the card status register. ++ * ++ * @param priv A pointer to uap_private structure ++ * @param bits the bit mask ++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE ++ */ ++static int ++mv_sdio_poll_card_status(uap_private * priv, u8 bits) ++{ ++ int tries; ++ u8 cs; ++ ++ ENTER(); ++ ++ for (tries = 0; tries < MAX_POLL_TRIES; tries++) { ++ if (sbi_read_ioreg(priv, CARD_STATUS_REG, &cs) < 0) ++ break; ++ else if ((cs & bits) == bits) { ++ LEAVE(); ++ return UAP_STATUS_SUCCESS; ++ } ++ udelay(10); ++ } ++ ++ PRINTM(WARN, "mv_sdio_poll_card_status failed, tries = %d\n", tries); ++ ++ LEAVE(); ++ return UAP_STATUS_FAILURE; ++} ++ ++/** ++ * @brief This function set the sdio bus width. ++ * ++ * @param priv A pointer to uap_private structure ++ * @param mode 1--1 bit mode, 4--4 bit mode ++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE ++ */ ++#if 0 ++static int ++sdio_set_bus_width(uap_private * priv, u8 mode) ++{ ++ ENTER(); ++ LEAVE(); ++ return UAP_STATUS_SUCCESS; ++} ++#endif ++ ++/** ++ * @brief This function reads data from the card. ++ * ++ * @param priv A pointer to uap_private structure ++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE ++ */ ++static int ++sd_card_to_host(uap_private * priv) ++{ ++ int ret = UAP_STATUS_SUCCESS; ++ u16 buf_len = 0; ++ int buf_block_len; ++ int blksz; ++ struct sk_buff *skb = NULL; ++ u16 type; ++ u8 *payload = NULL; ++ struct sdio_mmc_card *card = priv->uap_dev.card; ++ ++ ENTER(); ++ ++ if (!card || !card->func) { ++ PRINTM(ERROR, "card or function is NULL!\n"); ++ ret = UAP_STATUS_FAILURE; ++ goto exit; ++ } ++ ++ /* Read the length of data to be transferred */ ++ ret = sd_read_rx_len(priv, &buf_len); ++ if (ret < 0) { ++ PRINTM(ERROR, "card_to_host, read scratch reg failed\n"); ++ ret = UAP_STATUS_FAILURE; ++ goto exit; ++ } ++ ++ /* Allocate buffer */ ++ blksz = SD_BLOCK_SIZE; ++ buf_block_len = (buf_len + blksz - 1) / blksz; ++ if (buf_len <= INTF_HEADER_LEN || (buf_block_len * blksz) > ALLOC_BUF_SIZE) { ++ PRINTM(ERROR, "card_to_host, invalid packet length: %d\n", buf_len); ++ ret = UAP_STATUS_FAILURE; ++ goto exit; ++ } ++#ifdef PXA3XX_DMA_ALIGN ++ skb = dev_alloc_skb(buf_block_len * blksz + PXA3XX_DMA_ALIGNMENT); ++#else ++ skb = dev_alloc_skb(buf_block_len * blksz); ++#endif ++ if (skb == NULL) { ++ PRINTM(WARN, "No free skb\n"); ++ goto exit; ++ } ++#ifdef PXA3XX_DMA_ALIGN ++ if ((u32) skb->data & (PXA3XX_DMA_ALIGNMENT - 1)) { ++ skb_put(skb, (u32) skb->data & (PXA3XX_DMA_ALIGNMENT - 1)); ++ skb_pull(skb, (u32) skb->data & (PXA3XX_DMA_ALIGNMENT - 1)); ++ } ++#endif /* PXA3XX_DMA_ALIGN */ ++ ++ payload = skb->tail; ++ ret = sdio_readsb(card->func, payload, priv->uap_dev.ioport, ++ buf_block_len * blksz); ++ if (ret < 0) { ++ PRINTM(ERROR, "card_to_host, read iomem failed: %d\n", ret); ++ ret = UAP_STATUS_FAILURE; ++ goto exit; ++ } ++ HEXDUMP("SDIO Blk Rd", payload, blksz * buf_block_len); ++ /* ++ * This is SDIO specific header ++ * u16 length, ++ * u16 type (MV_TYPE_DAT = 0, MV_TYPE_CMD = 1, MV_TYPE_EVENT = 3) ++ */ ++ buf_len = uap_le16_to_cpu(*(u16 *) & payload[0]); ++ type = uap_le16_to_cpu(*(u16 *) & payload[2]); ++ switch (type) { ++ case MV_TYPE_EVENT: ++ skb_put(skb, buf_len); ++ skb_pull(skb, INTF_HEADER_LEN); ++ uap_process_event(priv, skb->data, skb->len); ++ kfree_skb(skb); ++ skb = NULL; ++ break; ++ case MV_TYPE_CMD: ++ skb_put(skb, buf_len); ++ skb_pull(skb, INTF_HEADER_LEN); ++ priv->adapter->cmd_pending = FALSE; ++ if (priv->adapter->cmd_wait_option == ++ HostCmd_OPTION_WAITFORRSP_SLEEPCONFIRM) { ++ priv->adapter->cmd_wait_option = FALSE; ++ uap_process_sleep_confirm_resp(priv, skb->data, skb->len); ++ } else if (priv->adapter->cmd_wait_option) { ++ memcpy(priv->adapter->CmdBuf, skb->data, skb->len); ++ priv->adapter->CmdSize = skb->len; ++ priv->adapter->cmd_wait_option = FALSE; ++ priv->adapter->CmdWaitQWoken = TRUE; ++ wake_up_interruptible(&priv->adapter->cmdwait_q); ++ } ++ kfree_skb(skb); ++ skb = NULL; ++ break; ++ case MV_TYPE_DAT: ++ skb_put(skb, buf_len); ++ skb_pull(skb, INTF_HEADER_LEN); ++ uap_process_rx_packet(priv, skb); ++ break; ++ default: ++ priv->stats.rx_errors++; ++ priv->stats.rx_dropped++; ++ /* Driver specified event and command resp should be handle here */ ++ PRINTM(INFO, "Unknown PKT type:%d\n", type); ++ kfree_skb(skb); ++ skb = NULL; ++ break; ++ } ++ exit: ++ if (ret) { ++ if (skb) ++ kfree_skb(skb); ++ } ++ ++ LEAVE(); ++ return ret; ++} ++ ++/** ++ * @brief This function enables the host interrupts mask ++ * ++ * @param priv A pointer to uap_private structure ++ * @param mask the interrupt mask ++ * @return UAP_STATUS_SUCCESS ++ */ ++static int ++enable_host_int_mask(uap_private * priv, u8 mask) ++{ ++ int ret = UAP_STATUS_SUCCESS; ++ ++ ENTER(); ++ ++ /* Simply write the mask to the register */ ++ ret = sbi_write_ioreg(priv, HOST_INT_MASK_REG, mask); ++ ++ if (ret) { ++ PRINTM(WARN, "Unable to enable the host interrupt!\n"); ++ ret = UAP_STATUS_FAILURE; ++ } ++ ++ LEAVE(); ++ return ret; ++} ++ ++/** @brief This function disables the host interrupts mask. ++ * ++ * @param priv A pointer to uap_private structure ++ * @param mask the interrupt mask ++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE ++ */ ++static int ++disable_host_int_mask(uap_private * priv, u8 mask) ++{ ++ int ret = UAP_STATUS_SUCCESS; ++ u8 host_int_mask; ++ ++ ENTER(); ++ ++ /* Read back the host_int_mask register */ ++ ret = sbi_read_ioreg(priv, HOST_INT_MASK_REG, &host_int_mask); ++ if (ret) { ++ ret = UAP_STATUS_FAILURE; ++ goto done; ++ } ++ ++ /* Update with the mask and write back to the register */ ++ host_int_mask &= ~mask; ++ ret = sbi_write_ioreg(priv, HOST_INT_MASK_REG, host_int_mask); ++ if (ret < 0) { ++ PRINTM(WARN, "Unable to diable the host interrupt!\n"); ++ ret = UAP_STATUS_FAILURE; ++ goto done; ++ } ++ ++ done: ++ LEAVE(); ++ return ret; ++} ++ ++/******************************************************** ++ Global Functions ++********************************************************/ ++ ++/** ++ * @brief This function handles the interrupt. ++ * ++ * @param func A pointer to sdio_func structure. ++ * @return n/a ++ */ ++static void ++sbi_interrupt(struct sdio_func *func) ++{ ++ struct sdio_mmc_card *card; ++ uap_private *priv; ++ u8 ireg = 0; ++ int ret = UAP_STATUS_SUCCESS; ++ ++ ENTER(); ++ ++ card = sdio_get_drvdata(func); ++ if (!card || !card->priv) { ++ PRINTM(MSG, "%s: sbi_interrupt(%p) card or priv is NULL, card=%p\n", ++ __FUNCTION__, func, card); ++ LEAVE(); ++ return; ++ } ++ priv = card->priv; ++#ifdef FW_WAKEUP_TIME ++ if ((priv->adapter->wt_pwrup_sending != 0L) && ++ (priv->adapter->wt_int == 0L)) ++ priv->adapter->wt_int = get_utimeofday(); ++#endif ++ ++ ireg = sdio_readb(card->func, HOST_INTSTATUS_REG, &ret); ++ if (ret) { ++ PRINTM(WARN, "sdio_read_ioreg: read int status register failed\n"); ++ goto done; ++ } ++ if (ireg != 0) { ++ /* ++ * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS ++ * Clear the interrupt status register and re-enable the interrupt ++ */ ++ PRINTM(INFO, "sdio_ireg = 0x%x\n", ireg); ++ sdio_writeb(card->func, ++ ~(ireg) & (DN_LD_HOST_INT_STATUS | UP_LD_HOST_INT_STATUS), ++ HOST_INTSTATUS_REG, &ret); ++ if (ret) { ++ PRINTM(WARN, ++ "sdio_write_ioreg: clear int status register failed\n"); ++ goto done; ++ } ++ } ++ OS_INT_DISABLE; ++ sd_ireg |= ireg; ++ OS_INT_RESTORE; ++ ++ uap_interrupt(priv); ++ done: ++ LEAVE(); ++} ++ ++/** ++ * @brief This function probe the card ++ * ++ * @param func A pointer to sdio_func structure ++ * @param id A pointer to structure sd_device_id ++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE ++ */ ++static int ++uap_probe(struct sdio_func *func, const struct sdio_device_id *id) ++{ ++ int ret = UAP_STATUS_FAILURE; ++ struct sdio_mmc_card *card = NULL; ++ ++ ENTER(); ++ ++ PRINTM(MSG, "%s: vendor=0x%4.04X device=0x%4.04X class=%d function=%d\n", ++ __FUNCTION__, func->vendor, func->device, func->class, func->num); ++ ++ card = kzalloc(sizeof(struct sdio_mmc_card), GFP_KERNEL); ++ if (!card) { ++ ret = -ENOMEM; ++ goto done; ++ } ++ ++ card->func = func; ++ ++ if (!uap_add_card(card)) { ++ PRINTM(ERROR, "%s: uap_add_callback failed\n", __FUNCTION__); ++ kfree(card); ++ ret = UAP_STATUS_FAILURE; ++ goto done; ++ } ++ ++ ret = UAP_STATUS_SUCCESS; ++ ++ done: ++ LEAVE(); ++ return ret; ++} ++ ++/** ++ * @brief This function removes the card ++ * ++ * @param func A pointer to sdio_func structure ++ * @return N/A ++ */ ++static void ++uap_remove(struct sdio_func *func) ++{ ++ struct sdio_mmc_card *card; ++ ++ ENTER(); ++ ++ if (func) { ++ card = sdio_get_drvdata(func); ++ if (card) { ++ uap_remove_card(card); ++ kfree(card); ++ } ++ } ++ ++ LEAVE(); ++} ++ ++#ifdef CONFIG_PM ++/** ++ * @brief This function handles client driver suspend ++ * ++ * @param func A pointer to sdio_func structure ++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE ++ */ ++int ++uap_suspend(struct sdio_func *func) ++{ ++ ENTER(); ++ LEAVE(); ++ return 0; ++} ++ ++/** ++ * @brief This function handles client driver resume ++ * ++ * @param func A pointer to sdio_func structure ++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE ++ */ ++int ++uap_resume(struct sdio_func *func) ++{ ++ ENTER(); ++ LEAVE(); ++ return 0; ++} ++#endif ++ ++/** Device ID for SD8688 */ ++#define SD_DEVICE_ID_8688_UAP 0x9104 ++/** UAP IDs */ ++static const struct sdio_device_id uap_ids[] = { ++ {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SD_DEVICE_ID_8688_UAP)}, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(sdio, uap_ids); ++ ++static struct sdio_driver uap_sdio = { ++ .name = "uap_sdio", ++ .id_table = uap_ids, ++ .probe = uap_probe, ++ .remove = uap_remove, ++#ifdef CONFIG_PM ++/* .suspend = uap_suspend, */ ++/* .resume = uap_resume, */ ++#endif ++ ++}; ++ ++/** ++ * @brief This function registers the IF module in bus driver. ++ * ++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE ++ */ ++int __init ++sbi_register() ++{ ++ int ret = UAP_STATUS_SUCCESS; ++ ++ ENTER(); ++ ++ /* SDIO Driver Registration */ ++ if (sdio_register_driver(&uap_sdio) != 0) { ++ PRINTM(FATAL, "SDIO Driver Registration Failed \n"); ++ ret = UAP_STATUS_FAILURE; ++ } ++ ++ LEAVE(); ++ return ret; ++} ++ ++/** ++ * @brief This function de-registers the IF module in bus driver. ++ * ++ * @return n/a ++ */ ++void __exit ++sbi_unregister(void) ++{ ++ ENTER(); ++ ++ /* SDIO Driver Unregistration */ ++ sdio_unregister_driver(&uap_sdio); ++ ++ LEAVE(); ++} ++ ++/** ++ * @brief This function checks the interrupt status and handle it accordingly. ++ * ++ * @param priv A pointer to uap_private structure ++ * @param ireg A pointer to variable that keeps returned value ++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE ++ */ ++int ++sbi_get_int_status(uap_private * priv, u8 * ireg) ++{ ++ int ret = UAP_STATUS_SUCCESS; ++ u8 sdio_ireg = 0; ++ struct sdio_mmc_card *card = priv->uap_dev.card; ++ ++ ENTER(); ++ ++ *ireg = 0; ++ OS_INT_DISABLE; ++ sdio_ireg = sd_ireg; ++ sd_ireg = 0; ++ OS_INT_RESTORE; ++ ++ sdio_claim_host(card->func); ++ ++ if (sdio_ireg & DN_LD_HOST_INT_STATUS) { /* tx_done INT */ ++ if (!priv->uap_dev.cmd_sent) { /* tx_done already received */ ++ PRINTM(INFO, ++ "warning: tx_done already received: tx_dnld_rdy=0x%x int status=0x%x\n", ++ priv->uap_dev.cmd_sent, sdio_ireg); ++ } else { ++ priv->uap_dev.cmd_sent = FALSE; ++ priv->uap_dev.data_sent = FALSE; ++ if ( (priv->uap_dev.netdev->reg_state == NETREG_REGISTERED) && (skb_queue_len(&priv->adapter->tx_queue) < TX_LOW_WATERMARK)) { ++ os_start_queue(priv); ++ } ++ } ++ } ++ if (sdio_ireg & UP_LD_HOST_INT_STATUS) { ++ sd_card_to_host(priv); ++ } ++ ++ *ireg = sdio_ireg; ++ ret = UAP_STATUS_SUCCESS; ++ sdio_release_host(card->func); ++ ++ LEAVE(); ++ return ret; ++} ++ ++/** ++ * @brief This function disables the host interrupts. ++ * ++ * @param priv A pointer to uap_private structure ++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE ++ */ ++int ++sbi_disable_host_int(uap_private * priv) ++{ ++ struct sdio_mmc_card *card = priv->uap_dev.card; ++ int ret; ++ ++ ENTER(); ++ ++ sdio_claim_host(card->func); ++ ret = disable_host_int_mask(priv, HIM_DISABLE); ++ sdio_release_host(card->func); ++ ++ LEAVE(); ++ return ret; ++} ++ ++/** ++ * @brief This function enables the host interrupts. ++ * ++ * @param priv A pointer to uap_private structure ++ * @return UAP_STATUS_SUCCESS ++ */ ++int ++sbi_enable_host_int(uap_private * priv) ++{ ++ struct sdio_mmc_card *card = priv->uap_dev.card; ++ int ret; ++ ++ ENTER(); ++ ++ sdio_claim_host(card->func); ++ ret = enable_host_int_mask(priv, HIM_ENABLE); ++ sdio_release_host(card->func); ++ ++ LEAVE(); ++ return ret; ++} ++ ++/** ++ * @brief This function de-registers the device. ++ * ++ * @param priv A pointer to uap_private structure ++ * @return UAP_STATUS_SUCCESS ++ */ ++int ++sbi_unregister_dev(uap_private * priv) ++{ ++ struct sdio_mmc_card *card = priv->uap_dev.card; ++ ++ ENTER(); ++ ++ if (!card || !card->func) { ++ PRINTM(ERROR, "Error: card or function is NULL!\n"); ++ goto done; ++ } ++ ++ sdio_claim_host(card->func); ++ sdio_release_irq(card->func); ++ sdio_disable_func(card->func); ++ sdio_release_host(card->func); ++ ++ sdio_set_drvdata(card->func, NULL); ++ ++ done: ++ LEAVE(); ++ return UAP_STATUS_SUCCESS; ++} ++ ++/** ++ * @brief This function registers the device. ++ * ++ * @param priv A pointer to uap_private structure ++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE ++ */ ++int ++sbi_register_dev(uap_private * priv) ++{ ++ int ret = UAP_STATUS_FAILURE; ++ u8 reg; ++ struct sdio_mmc_card *card = priv->uap_dev.card; ++ struct sdio_func *func; ++ ++ ENTER(); ++ ++ if (!card || !card->func) { ++ PRINTM(ERROR, "Error: card or function is NULL!\n"); ++ goto done; ++ } ++ ++ func = card->func; ++ ++ /* Initialize the private structure */ ++ priv->uap_dev.ioport = 0; ++ ++ sdio_claim_host(func); ++ ++ ret = sdio_enable_func(func); ++ if (ret) { ++ PRINTM(FATAL, "sdio_enable_func() failed: ret=%d\n", ret); ++ goto release_host; ++ } ++ ++ ret = sdio_claim_irq(func, sbi_interrupt); ++ if (ret) { ++ PRINTM(FATAL, "sdio_claim_irq failed: ret=%d\n", ret); ++ goto disable_func; ++ } ++ ++ /* Read the IO port */ ++ ret = sbi_read_ioreg(priv, IO_PORT_0_REG, ®); ++ if (ret) ++ goto release_irq; ++ else ++ priv->uap_dev.ioport |= reg; ++ ++ ret = sbi_read_ioreg(priv, IO_PORT_1_REG, ®); ++ if (ret) ++ goto release_irq; ++ else ++ priv->uap_dev.ioport |= (reg << 8); ++ ++ ret = sbi_read_ioreg(priv, IO_PORT_2_REG, ®); ++ if (ret) ++ goto release_irq; ++ else ++ priv->uap_dev.ioport |= (reg << 16); ++ ++ PRINTM(INFO, "SDIO FUNC #%d IO port: 0x%x\n", func->num, ++ priv->uap_dev.ioport); ++ ++ ret = sdio_set_block_size(card->func, SD_BLOCK_SIZE); ++ if (ret) { ++ PRINTM(ERROR, "%s: cannot set SDIO block size\n", __FUNCTION__); ++ ret = UAP_STATUS_FAILURE; ++ goto release_irq; ++ } ++ priv->hotplug_device = &func->dev; ++ ++ if (helper_name == NULL) { ++ helper_name = DEFAULT_HELPER_NAME; ++ } ++ if (fw_name == NULL) { ++ fw_name = DEFAULT_FW_NAME; ++ } ++ sdio_release_host(func); ++ ++ sdio_set_drvdata(func, card); ++ ++ ret = UAP_STATUS_SUCCESS; ++ goto done; ++ ++ release_irq: ++ sdio_release_irq(func); ++ disable_func: ++ sdio_disable_func(func); ++ release_host: ++ sdio_release_host(func); ++ ++ done: ++ LEAVE(); ++ return ret; ++} ++ ++/** ++ * @brief This function sends data to the card. ++ * ++ * @param priv A pointer to uap_private structure ++ * @param payload A pointer to the data/cmd buffer ++ * @param nb the length of data/cmd ++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE ++ */ ++int ++sbi_host_to_card(uap_private * priv, u8 * payload, u16 nb) ++{ ++ struct sdio_mmc_card *card = priv->uap_dev.card; ++ int ret = UAP_STATUS_SUCCESS; ++ int buf_block_len; ++ int blksz; ++ int i = 0; ++ u8 *buf = NULL; ++#ifdef PXA3XX_DMA_ALIGN ++ void *tmpbuf = NULL; ++ int tmpbufsz; ++#endif ++ ++ ENTER(); ++ ++ if (!card || !card->func) { ++ PRINTM(ERROR, "card or function is NULL!\n"); ++ LEAVE(); ++ return UAP_STATUS_FAILURE; ++ } ++ buf = payload; ++#ifdef PXA3XX_DMA_ALIGN ++ if ((u32) payload & (PXA3XX_DMA_ALIGNMENT - 1)) { ++ tmpbufsz = ALIGN_SZ(nb, PXA3XX_DMA_ALIGNMENT); ++ tmpbuf = kmalloc(tmpbufsz, GFP_KERNEL); ++ memset(tmpbuf, 0, tmpbufsz); ++ /* Ensure 8-byte aligned CMD buffer */ ++ buf = (u8 *) ALIGN_ADDR(tmpbuf, PXA3XX_DMA_ALIGNMENT); ++ memcpy(buf, payload, nb); ++ } ++#endif ++ /* Allocate buffer and copy payload */ ++ blksz = SD_BLOCK_SIZE; ++ buf_block_len = (nb + blksz - 1) / blksz; ++ sdio_claim_host(card->func); ++#define MAX_WRITE_IOMEM_RETRY 2 ++ priv->uap_dev.cmd_sent = TRUE; ++ priv->uap_dev.data_sent = TRUE; ++ do { ++ /* Transfer data to card */ ++ ret = sdio_writesb(card->func, priv->uap_dev.ioport, buf, ++ buf_block_len * blksz); ++ if (ret < 0) { ++ i++; ++ PRINTM(ERROR, "host_to_card, write iomem (%d) failed: %d\n", i, ++ ret); ++ ret = UAP_STATUS_FAILURE; ++ if (i > MAX_WRITE_IOMEM_RETRY) ++ goto exit; ++ } else { ++ HEXDUMP("SDIO Blk Wr", payload, nb); ++ } ++ } while (ret == UAP_STATUS_FAILURE); ++ exit: ++ sdio_release_host(card->func); ++#ifdef PXA3XX_DMA_ALIGN ++ if (tmpbuf) ++ kfree(tmpbuf); ++#endif ++ if (ret == UAP_STATUS_FAILURE) { ++ priv->uap_dev.cmd_sent = FALSE; ++ priv->uap_dev.data_sent = FALSE; ++ } ++ LEAVE(); ++ return ret; ++} ++ ++/** ++ * @brief This function reads CIS information. ++ * ++ * @param priv A pointer to uap_private structure ++ * @param cisinfo A pointer to CIS information output buffer ++ * @param cislen A pointer to length of CIS info output buffer ++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE ++ */ ++#if 0 ++static int ++sbi_get_cis_info(uap_private * priv, void *cisinfo, int *cislen) ++{ ++#define CIS_PTR (0x8000) ++ struct sdio_mmc_card *card = priv->uap_dev.card; ++ unsigned int i, cis_ptr = CIS_PTR; ++ int ret = UAP_STATUS_FAILURE; ++ ++ ENTER(); ++ ++ if (!card || !card->func) { ++ PRINTM(ERROR, "sbi_get_cis_info(): card or function is NULL!\n"); ++ goto exit; ++ } ++#define MAX_SDIO_CIS_INFO_LEN (256) ++ if (!cisinfo || (*cislen < MAX_SDIO_CIS_INFO_LEN)) { ++ PRINTM(WARN, "ERROR! get_cis_info: insufficient buffer passed\n"); ++ goto exit; ++ } ++ ++ *cislen = MAX_SDIO_CIS_INFO_LEN; ++ ++ sdio_claim_host(card->func); ++ ++ PRINTM(INFO, "cis_ptr=%#x\n", cis_ptr); ++ ++ /* Read the Tuple Data */ ++ for (i = 0; i < *cislen; i++) { ++ ((unsigned char *) cisinfo)[i] = ++ sdio_readb(card->func, cis_ptr + i, &ret); ++ if (ret) { ++ PRINTM(WARN, "get_cis_info error: ret=%d\n", ret); ++ ret = UAP_STATUS_FAILURE; ++ goto done; ++ } ++ PRINTM(INFO, "cisinfo[%d]=%#x\n", i, ((unsigned char *) cisinfo)[i]); ++ } ++ ++ done: ++ sdio_release_host(card->func); ++ exit: ++ LEAVE(); ++ return ret; ++} ++#endif ++/** ++ * @brief This function downloads helper image to the card. ++ * ++ * @param priv A pointer to uap_private structure ++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE ++ */ ++int ++sbi_prog_helper(uap_private * priv) ++{ ++ struct sdio_mmc_card *card = priv->uap_dev.card; ++ u8 *helper = NULL; ++ int helperlen; ++ int ret = UAP_STATUS_SUCCESS; ++ void *tmphlprbuf = NULL; ++ int tmphlprbufsz; ++ u8 *hlprbuf; ++ int hlprblknow; ++ u32 tx_len; ++#ifdef FW_DOWNLOAD_SPEED ++ u32 tv1, tv2; ++#endif ++ ++ ENTER(); ++ ++ if (!card || !card->func) { ++ PRINTM(ERROR, "sbi_prog_helper(): card or function is NULL!\n"); ++ goto done; ++ } ++ ++ if (priv->fw_helper) { ++ helper = (u8 *) priv->fw_helper->data; ++ helperlen = priv->fw_helper->size; ++ } else { ++ PRINTM(MSG, "No helper image found! Terminating download.\n"); ++ LEAVE(); ++ return UAP_STATUS_FAILURE; ++ } ++ ++ PRINTM(INFO, "Downloading helper image (%d bytes), block size %d bytes\n", ++ helperlen, SD_BLOCK_SIZE); ++ ++#ifdef FW_DOWNLOAD_SPEED ++ tv1 = get_utimeofday(); ++#endif ++ ++#ifdef PXA3XX_DMA_ALIGN ++ tmphlprbufsz = ALIGN_SZ(UAP_UPLD_SIZE, PXA3XX_DMA_ALIGNMENT); ++#else /* !PXA3XX_DMA_ALIGN */ ++ tmphlprbufsz = UAP_UPLD_SIZE; ++#endif /* !PXA3XX_DMA_ALIGN */ ++ tmphlprbuf = kmalloc(tmphlprbufsz, GFP_KERNEL); ++ if (!tmphlprbuf) { ++ PRINTM(ERROR, ++ "Unable to allocate buffer for helper. Terminating download\n"); ++ ret = UAP_STATUS_FAILURE; ++ goto done; ++ } ++ memset(tmphlprbuf, 0, tmphlprbufsz); ++#ifdef PXA3XX_DMA_ALIGN ++ hlprbuf = (u8 *) ALIGN_ADDR(tmphlprbuf, PXA3XX_DMA_ALIGNMENT); ++#else /* !PXA3XX_DMA_ALIGN */ ++ hlprbuf = (u8 *) tmphlprbuf; ++#endif /* !PXA3XX_DMA_ALIGN */ ++ ++ sdio_claim_host(card->func); ++ ++ /* Perform helper data transfer */ ++ tx_len = (FIRMWARE_TRANSFER_NBLOCK * SD_BLOCK_SIZE) - INTF_HEADER_LEN; ++ hlprblknow = 0; ++ do { ++ /* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY bits */ ++ ret = mv_sdio_poll_card_status(priv, CARD_IO_READY | DN_LD_CARD_RDY); ++ if (ret < 0) { ++ PRINTM(FATAL, "Helper download poll status timeout @ %d\n", ++ hlprblknow); ++ goto done; ++ } ++ ++ /* More data? */ ++ if (hlprblknow >= helperlen) ++ break; ++ ++ /* Set blocksize to transfer - checking for last block */ ++ if (helperlen - hlprblknow < tx_len) ++ tx_len = helperlen - hlprblknow; ++ ++ /* Set length to the 4-byte header */ ++ *(u32 *) hlprbuf = uap_cpu_to_le32(tx_len); ++ ++ /* Copy payload to buffer */ ++ memcpy(&hlprbuf[INTF_HEADER_LEN], &helper[hlprblknow], tx_len); ++ ++ PRINTM(INFO, "."); ++ ++ /* Send data */ ++ ret = sdio_writesb(card->func, priv->uap_dev.ioport, ++ hlprbuf, FIRMWARE_TRANSFER_NBLOCK * SD_BLOCK_SIZE); ++ ++ if (ret < 0) { ++ PRINTM(FATAL, "IO error during helper download @ %d\n", hlprblknow); ++ goto done; ++ } ++ ++ hlprblknow += tx_len; ++ } while (TRUE); ++ ++#ifdef FW_DOWNLOAD_SPEED ++ tv2 = get_utimeofday(); ++ PRINTM(INFO, "helper: %ld.%03ld.%03ld ", tv1 / 1000000, ++ (tv1 % 1000000) / 1000, tv1 % 1000); ++ PRINTM(INFO, " -> %ld.%03ld.%03ld ", tv2 / 1000000, (tv2 % 1000000) / 1000, ++ tv2 % 1000); ++ tv2 -= tv1; ++ PRINTM(INFO, " == %ld.%03ld.%03ld\n", tv2 / 1000000, (tv2 % 1000000) / 1000, ++ tv2 % 1000); ++#endif ++ ++ /* Write last EOF data */ ++ PRINTM(INFO, "\nTransferring helper image EOF block\n"); ++ memset(hlprbuf, 0x0, SD_BLOCK_SIZE); ++ ret = sdio_writesb(card->func, priv->uap_dev.ioport, ++ hlprbuf, SD_BLOCK_SIZE); ++ ++ if (ret < 0) { ++ PRINTM(FATAL, "IO error in writing helper image EOF block\n"); ++ goto done; ++ } ++ ++ ret = UAP_STATUS_SUCCESS; ++ ++ done: ++ sdio_release_host(card->func); ++ if (tmphlprbuf) ++ kfree(tmphlprbuf); ++ ++ LEAVE(); ++ return ret; ++} ++ ++/** ++ * @brief This function downloads firmware image to the card. ++ * ++ * @param priv A pointer to uap_private structure ++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE ++ */ ++int ++sbi_prog_fw_w_helper(uap_private * priv) ++{ ++ struct sdio_mmc_card *card = priv->uap_dev.card; ++ u8 *firmware = NULL; ++ int firmwarelen; ++ u8 base0; ++ u8 base1; ++ int ret = UAP_STATUS_SUCCESS; ++ int offset; ++ void *tmpfwbuf = NULL; ++ int tmpfwbufsz; ++ u8 *fwbuf; ++ u16 len; ++ int txlen = 0; ++ int tx_blocks = 0; ++ int i = 0; ++ int tries = 0; ++#ifdef FW_DOWNLOAD_SPEED ++ u32 tv1, tv2; ++#endif ++ ++ ENTER(); ++ ++ if (!card || !card->func) { ++ PRINTM(ERROR, "sbi_prog_fw_w_helper(): card or function is NULL!\n"); ++ goto done; ++ } ++ ++ if (priv->firmware) { ++ firmware = (u8 *) priv->firmware->data; ++ firmwarelen = priv->firmware->size; ++ } else { ++ PRINTM(MSG, "No firmware image found! Terminating download.\n"); ++ LEAVE(); ++ return UAP_STATUS_FAILURE; ++ } ++ ++ PRINTM(INFO, "Downloading FW image (%d bytes)\n", firmwarelen); ++ ++#ifdef FW_DOWNLOAD_SPEED ++ tv1 = get_utimeofday(); ++#endif ++ ++#ifdef PXA3XX_DMA_ALIGN ++ tmpfwbufsz = ALIGN_SZ(UAP_UPLD_SIZE, PXA3XX_DMA_ALIGNMENT); ++#else /* PXA3XX_DMA_ALIGN */ ++ tmpfwbufsz = UAP_UPLD_SIZE; ++#endif /* PXA3XX_DMA_ALIGN */ ++ tmpfwbuf = kmalloc(tmpfwbufsz, GFP_KERNEL); ++ if (!tmpfwbuf) { ++ PRINTM(ERROR, ++ "Unable to allocate buffer for firmware. Terminating download.\n"); ++ ret = UAP_STATUS_FAILURE; ++ goto done; ++ } ++ memset(tmpfwbuf, 0, tmpfwbufsz); ++#ifdef PXA3XX_DMA_ALIGN ++ /* Ensure 8-byte aligned firmware buffer */ ++ fwbuf = (u8 *) ALIGN_ADDR(tmpfwbuf, PXA3XX_DMA_ALIGNMENT); ++#else /* PXA3XX_DMA_ALIGN */ ++ fwbuf = (u8 *) tmpfwbuf; ++#endif /* PXA3XX_DMA_ALIGN */ ++ ++ sdio_claim_host(card->func); ++ ++ /* Perform firmware data transfer */ ++ offset = 0; ++ do { ++ /* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY bits */ ++ ret = mv_sdio_poll_card_status(priv, CARD_IO_READY | DN_LD_CARD_RDY); ++ if (ret < 0) { ++ PRINTM(FATAL, "FW download with helper poll status timeout @ %d\n", ++ offset); ++ goto done; ++ } ++ ++ /* More data? */ ++ if (offset >= firmwarelen) ++ break; ++ ++ for (tries = 0; tries < MAX_POLL_TRIES; tries++) { ++ if ((ret = sbi_read_ioreg(priv, HOST_F1_RD_BASE_0, &base0)) < 0) { ++ PRINTM(WARN, "Dev BASE0 register read failed:" ++ " base0=0x%04X(%d). Terminating download.\n", base0, ++ base0); ++ ret = UAP_STATUS_FAILURE; ++ goto done; ++ } ++ if ((ret = sbi_read_ioreg(priv, HOST_F1_RD_BASE_1, &base1)) < 0) { ++ PRINTM(WARN, "Dev BASE1 register read failed:" ++ " base1=0x%04X(%d). Terminating download.\n", base1, ++ base1); ++ ret = UAP_STATUS_FAILURE; ++ goto done; ++ } ++ len = (((u16) base1) << 8) | base0; ++ ++ /* For SD8688 wait until the length is not 0, 1 or 2 before ++ downloading the first FW block, since BOOT code writes the ++ register to indicate the helper/FW download winner, the value ++ could be 1 or 2 (Func1 or Func2). */ ++ if ((len && offset) || (len > 2)) ++ break; ++ udelay(10); ++ } ++ ++ if (len == 0) ++ break; ++ else if (len > UAP_UPLD_SIZE) { ++ PRINTM(FATAL, "FW download failure @ %d, invalid length %d\n", ++ offset, len); ++ ret = UAP_STATUS_FAILURE; ++ goto done; ++ } ++ ++ txlen = len; ++ ++ if (len & BIT(0)) { ++ i++; ++ if (i > MAX_WRITE_IOMEM_RETRY) { ++ PRINTM(FATAL, ++ "FW download failure @ %d, over max retry count\n", ++ offset); ++ ret = UAP_STATUS_FAILURE; ++ goto done; ++ } ++ PRINTM(ERROR, "FW CRC error indicated by the helper:" ++ " len = 0x%04X, txlen = %d\n", len, txlen); ++ len &= ~BIT(0); ++ /* Setting this to 0 to resend from same offset */ ++ txlen = 0; ++ } else { ++ i = 0; ++ ++ /* Set blocksize to transfer - checking for last block */ ++ if (firmwarelen - offset < txlen) { ++ txlen = firmwarelen - offset; ++ } ++ PRINTM(INFO, "."); ++ ++ tx_blocks = (txlen + SD_BLOCK_SIZE - 1) / SD_BLOCK_SIZE; ++ ++ /* Copy payload to buffer */ ++ memcpy(fwbuf, &firmware[offset], txlen); ++ } ++ ++ /* Send data */ ++ ret = sdio_writesb(card->func, priv->uap_dev.ioport, ++ fwbuf, tx_blocks * SD_BLOCK_SIZE); ++ ++ if (ret < 0) { ++ PRINTM(ERROR, "FW download, write iomem (%d) failed @ %d\n", i, ++ offset); ++ if (sbi_write_ioreg(priv, CONFIGURATION_REG, 0x04) < 0) { ++ PRINTM(ERROR, "write ioreg failed (CFG)\n"); ++ } ++ } ++ ++ offset += txlen; ++ } while (TRUE); ++ ++ PRINTM(INFO, "\nFW download over, size %d bytes\n", offset); ++ ++ ret = UAP_STATUS_SUCCESS; ++ done: ++#ifdef FW_DOWNLOAD_SPEED ++ tv2 = get_utimeofday(); ++ PRINTM(INFO, "FW: %ld.%03ld.%03ld ", tv1 / 1000000, ++ (tv1 % 1000000) / 1000, tv1 % 1000); ++ PRINTM(INFO, " -> %ld.%03ld.%03ld ", tv2 / 1000000, ++ (tv2 % 1000000) / 1000, tv2 % 1000); ++ tv2 -= tv1; ++ PRINTM(INFO, " == %ld.%03ld.%03ld\n", tv2 / 1000000, ++ (tv2 % 1000000) / 1000, tv2 % 1000); ++#endif ++ sdio_release_host(card->func); ++ if (tmpfwbuf) ++ kfree(tmpfwbuf); ++ ++ LEAVE(); ++ return ret; ++} ++ ++/** ++ * @brief This function checks if the firmware is ready to accept ++ * command or not. ++ * ++ * @param priv A pointer to uap_private structure ++ * @param pollnum Poll number ++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE ++ */ ++int ++sbi_check_fw_status(uap_private * priv, int pollnum) ++{ ++ struct sdio_mmc_card *card = priv->uap_dev.card; ++ int ret = UAP_STATUS_SUCCESS; ++ u16 firmwarestat; ++ int tries; ++ ++ ENTER(); ++ ++ sdio_claim_host(card->func); ++ ++ /* Wait for firmware initialization event */ ++ for (tries = 0; tries < pollnum; tries++) { ++ if ((ret = sd_read_firmware_status(priv, &firmwarestat)) < 0) ++ continue; ++ if (firmwarestat == FIRMWARE_READY) { ++ ret = UAP_STATUS_SUCCESS; ++ break; ++ } else { ++ mdelay(10); ++ ret = UAP_STATUS_FAILURE; ++ } ++ } ++ ++ if (ret < 0) ++ goto done; ++ ++ ret = UAP_STATUS_SUCCESS; ++ sd_get_rx_unit(priv); ++ ++ done: ++ sdio_release_host(card->func); ++ ++ LEAVE(); ++ return ret; ++} ++ ++/** ++ * @brief This function set bus clock on/off ++ * ++ * @param priv A pointer to uap_private structure ++ * @param option TRUE--on , FALSE--off ++ * @return UAP_STATUS_SUCCESS ++ */ ++#if 0 ++static int ++sbi_set_bus_clock(uap_private * priv, u8 option) ++{ ++ ENTER(); ++ LEAVE(); ++ return UAP_STATUS_SUCCESS; ++} ++#endif ++ ++/** ++ * @brief This function wakeup firmware ++ * ++ * @param priv A pointer to uap_private structure ++ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE ++ */ ++int ++sbi_wakeup_firmware(uap_private * priv) ++{ ++ struct sdio_mmc_card *card = priv->uap_dev.card; ++ int ret = UAP_STATUS_SUCCESS; ++ ++ ENTER(); ++ ++ if (!card || !card->func) { ++ PRINTM(ERROR, "card or function is NULL!\n"); ++ LEAVE(); ++ return UAP_STATUS_FAILURE; ++ } ++ sdio_claim_host(card->func); ++ sdio_writeb(card->func, HOST_POWER_UP, CONFIGURATION_REG, &ret); ++ sdio_release_host(card->func); ++ LEAVE(); ++ return ret; ++} +diff -Naupr linux-2.6.37/drivers/net/wireless/libertas_uap/uap_sdio_mmc.h linux-2.6.37-new/drivers/net/wireless/libertas_uap/uap_sdio_mmc.h +--- linux-2.6.37/drivers/net/wireless/libertas_uap/uap_sdio_mmc.h 1969-12-31 17:00:00.000000000 -0700 ++++ linux-2.6.37-new/drivers/net/wireless/libertas_uap/uap_sdio_mmc.h 2011-01-08 06:01:04.057834571 -0700 +@@ -0,0 +1,136 @@ ++/** @file uap_sdio_mmc.h ++ * @brief This file contains SDIO IF (interface) module ++ * related macros, enum, and structure. ++ * ++ * Copyright (C) 2007-2009, Marvell International Ltd. ++ * ++ * This software file (the "File") is distributed by Marvell International ++ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 ++ * (the "License"). You may use, redistribute and/or modify this File in ++ * accordance with the terms and conditions of the License, a copy of which ++ * is available along with the File in the gpl.txt file or by writing to ++ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. ++ * ++ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ++ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about ++ * this warranty disclaimer. ++ * ++ */ ++/**************************************************** ++Change log: ++ 10/10/07: initial version ++****************************************************/ ++ ++#ifndef _UAP_SDIO_MMC_H ++#define _UAP_SDIO_MMC_H ++ ++#include ++#include ++#include ++#include ++ ++#include "uap_headers.h" ++ ++/** The number of times to try when waiting for downloaded firmware to ++ become active. (polling the scratch register). */ ++#define MAX_FIRMWARE_POLL_TRIES 100 ++ ++/** Firmware ready */ ++#define FIRMWARE_READY 0xfedc ++ ++/** Number of firmware blocks to transfer */ ++#define FIRMWARE_TRANSFER_NBLOCK 2 ++ ++/* Host Control Registers */ ++/** Host Control Registers : I/O port 0 */ ++#define IO_PORT_0_REG 0x00 ++/** Host Control Registers : I/O port 1 */ ++#define IO_PORT_1_REG 0x01 ++/** Host Control Registers : I/O port 2 */ ++#define IO_PORT_2_REG 0x02 ++ ++/** Host Control Registers : Configuration */ ++#define CONFIGURATION_REG 0x03 ++/** Host Control Registers : Host without Command 53 finish host */ ++#define HOST_WO_CMD53_FINISH_HOST (0x1U << 2) ++/** Host Control Registers : Host power up */ ++#define HOST_POWER_UP (0x1U << 1) ++/** Host Control Registers : Host power down */ ++#define HOST_POWER_DOWN (0x1U << 0) ++ ++/** Host Control Registers : Host interrupt mask */ ++#define HOST_INT_MASK_REG 0x04 ++/** Host Control Registers : Upload host interrupt mask */ ++#define UP_LD_HOST_INT_MASK (0x1U) ++/** Host Control Registers : Download host interrupt mask */ ++#define DN_LD_HOST_INT_MASK (0x2U) ++/** Enable Host interrupt mask */ ++#define HIM_ENABLE (UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK) ++/** Disable Host interrupt mask */ ++#define HIM_DISABLE 0xff ++ ++/** Host Control Registers : Host interrupt status */ ++#define HOST_INTSTATUS_REG 0x05 ++/** Host Control Registers : Upload host interrupt status */ ++#define UP_LD_HOST_INT_STATUS (0x1U) ++/** Host Control Registers : Download host interrupt status */ ++#define DN_LD_HOST_INT_STATUS (0x2U) ++ ++/** Host F1 read base 0 */ ++#define HOST_F1_RD_BASE_0 0x10 ++/** Host F1 read base 1 */ ++#define HOST_F1_RD_BASE_1 0x11 ++ ++/** Card Control Registers : Card status register */ ++#define CARD_STATUS_REG 0x20 ++/** Card Control Registers : Card I/O ready */ ++#define CARD_IO_READY (0x1U << 3) ++/** Card Control Registers : CIS card ready */ ++#define CIS_CARD_RDY (0x1U << 2) ++/** Card Control Registers : Upload card ready */ ++#define UP_LD_CARD_RDY (0x1U << 1) ++/** Card Control Registers : Download card ready */ ++#define DN_LD_CARD_RDY (0x1U << 0) ++ ++/** Card Control Registers : Card OCR 0 register */ ++#define CARD_OCR_0_REG 0x34 ++/** Card Control Registers : Card OCR 1 register */ ++#define CARD_OCR_1_REG 0x35 ++ ++/** Firmware status 0 register */ ++#define CARD_FW_STATUS0_REG 0x40 ++/** Firmware status 1 register */ ++#define CARD_FW_STATUS1_REG 0x41 ++/** Rx length register */ ++#define CARD_RX_LEN_REG 0x42 ++/** Rx unit register */ ++#define CARD_RX_UNIT_REG 0x43 ++ ++/** Chip Id Register 0 */ ++#define CARD_CHIP_ID_0_REG 0x801c ++/** Chip Id Register 1 */ ++#define CARD_CHIP_ID_1_REG 0x801d ++ ++#ifdef PXA3XX_DMA_ALIGN ++/** DMA alignment value for PXA3XX platforms */ ++#define PXA3XX_DMA_ALIGNMENT 8 ++/** Macros for Data Alignment : size */ ++#define ALIGN_SZ(p, a) \ ++ (((p) + ((a) - 1)) & ~((a) - 1)) ++ ++/** Macros for Data Alignment : address */ ++#define ALIGN_ADDR(p, a) \ ++ ((((u32)(p)) + (((u32)(a)) - 1)) & ~(((u32)(a)) - 1)) ++#endif /* PXA3XX_DMA_ALIGN */ ++ ++struct sdio_mmc_card ++{ ++ /** sdio_func structure pointer */ ++ struct sdio_func *func; ++ /** uap_private structure pointer */ ++ uap_private *priv; ++}; ++ ++#endif /* _UAP_SDIO_MMC_H */ diff --git a/with-linux-3.2/linux-3.0.4-LIBERTAS-WEXT_PRIV.patch b/with-linux-3.2/linux-3.0.4-LIBERTAS-WEXT_PRIV.patch new file mode 100644 index 0000000..2c91ef1 --- /dev/null +++ b/with-linux-3.2/linux-3.0.4-LIBERTAS-WEXT_PRIV.patch @@ -0,0 +1,10 @@ +--- ./drivers/net/wireless/libertas/Kconfig.orig 2011-08-29 14:56:30.000000000 -0600 ++++ ./drivers/net/wireless/libertas/Kconfig 2011-09-13 20:37:23.660904556 -0600 +@@ -3,6 +3,7 @@ config LIBERTAS + depends on CFG80211 + select WIRELESS_EXT + select WEXT_SPY ++ select WEXT_PRIV + select LIB80211 + select FW_LOADER + ---help--- diff --git a/with-linux-3.2/mvsdio-1-2.6.30.patch b/with-linux-3.2/mvsdio-1-2.6.30.patch new file mode 100644 index 0000000..63f0156 --- /dev/null +++ b/with-linux-3.2/mvsdio-1-2.6.30.patch @@ -0,0 +1,18 @@ +--- ./drivers/mmc/host/mvsdio.c.orig 2009-06-09 21:05:27.000000000 -0600 ++++ ./drivers/mmc/host/mvsdio.c 2009-06-23 23:20:36.085662093 -0600 +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -148,6 +149,7 @@ static void mvsd_request(struct mmc_host + + dev_dbg(host->dev, "cmd %d (hw state 0x%04x)\n", + cmd->opcode, mvsd_read(MVSD_HW_STATE)); ++ if (cmd->opcode == SD_SWITCH) mdelay(1); /* Voodoo */ + + cmdreg = MVSD_CMD_INDEX(cmd->opcode); + diff --git a/with-linux-3.2/mvsdio-1-2.6.30.patch.larger b/with-linux-3.2/mvsdio-1-2.6.30.patch.larger new file mode 100644 index 0000000..6ab7d92 --- /dev/null +++ b/with-linux-3.2/mvsdio-1-2.6.30.patch.larger @@ -0,0 +1,32 @@ +--- ./drivers/mmc/core/core.c.orig 2009-06-09 21:05:27.000000000 -0600 ++++ ./drivers/mmc/core/core.c 2009-06-23 23:24:58.473855897 -0600 +@@ -286,9 +286,9 @@ void mmc_set_data_timeout(struct mmc_dat + * The limit is really 250 ms, but that is + * insufficient for some crappy cards. + */ +- limit_us = 300000; ++ limit_us = 500000; + else +- limit_us = 100000; ++ limit_us = 200000; + + /* + * SDHC cards always use these fixed values. +--- ./drivers/mmc/host/mvsdio.c.orig 2009-06-09 21:05:27.000000000 -0600 ++++ ./drivers/mmc/host/mvsdio.c 2009-06-23 23:20:36.085662093 -0600 +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -148,6 +149,7 @@ static void mvsd_request(struct mmc_host + + dev_dbg(host->dev, "cmd %d (hw state 0x%04x)\n", + cmd->opcode, mvsd_read(MVSD_HW_STATE)); ++ if (cmd->opcode == SD_SWITCH) mdelay(1); /* Voodoo */ + + cmdreg = MVSD_CMD_INDEX(cmd->opcode); + diff --git a/with-linux-3.2/mvsdio-2.patch b/with-linux-3.2/mvsdio-2.patch new file mode 100644 index 0000000..8d53f2a --- /dev/null +++ b/with-linux-3.2/mvsdio-2.patch @@ -0,0 +1,35 @@ +From: Nicolas Pitre +Date: Tue, 28 Apr 2009 02:38:12 +0000 (-0400) +Subject: [MMC] give Sandisk/Kingston SDHC cards some slack before the SWITCH command +X-Git-Url: http://git.marvell.com/?p=orion.git;a=commitdiff_plain;h=3ea638523747f6d312f11f643a3175c1a4661eec;hp=c0c3df02efed0e5dea9aa4d8313e06e1f68f2cb4 + +[MMC] give Sandisk/Kingston SDHC cards some slack before the SWITCH command + +Without this delay, those cards simply won't work in high speed mode +as the SWITCH command does not succeeds. + +Signed-off-by: Nicolas Pitre +Tested-by: Martin Michlmayr +--- + +diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c +index cd81c39..ba4c7ab 100644 +--- a/drivers/mmc/core/sd.c ++++ b/drivers/mmc/core/sd.c +@@ -263,6 +263,15 @@ static int mmc_switch_hs(struct mmc_card *card) + return -ENOMEM; + } + ++ /* ++ * Some SDHC cards, notably those with a Sandisk SD controller ++ * (also found in Kingston products) need a bit of slack ++ * before successfully handling the SWITCH command. So far, ++ * cards identifying themselves as "SD04G" and "SD08G" are ++ * affected ++ */ ++ udelay(100); ++ + err = mmc_sd_switch(card, 1, 0, 1, status); + if (err) + goto out; + diff --git a/with-linux-3.2/mvsdio-3.patch b/with-linux-3.2/mvsdio-3.patch new file mode 100644 index 0000000..76e96ce --- /dev/null +++ b/with-linux-3.2/mvsdio-3.patch @@ -0,0 +1,13 @@ +Index: linux-3.4/drivers/mmc/core/core.c +=================================================================== +--- linux-3.4.orig/drivers/mmc/core/core.c 2012-05-27 15:26:08.394167850 -0300 ++++ linux-3.4/drivers/mmc/core/core.c 2012-05-27 15:26:38.085113097 -0300 +@@ -536,7 +536,7 @@ + */ + limit_us = 3000000; + else +- limit_us = 100000; ++ limit_us = 200000; + + /* + * SDHC cards always use these fixed values. diff --git a/with-linux-3.2/phys-virt.diff b/with-linux-3.2/phys-virt.diff new file mode 100644 index 0000000..fc3d43e --- /dev/null +++ b/with-linux-3.2/phys-virt.diff @@ -0,0 +1,14 @@ +Index: linux-3.4/arch/arm/Kconfig +=================================================================== +--- linux-3.4.orig/arch/arm/Kconfig 2012-05-27 17:00:06.244112647 -0300 ++++ linux-3.4/arch/arm/Kconfig 2012-05-27 17:01:06.456038133 -0300 +@@ -235,8 +235,7 @@ + + config PHYS_OFFSET + hex "Physical address of main memory" if MMU +- depends on !ARM_PATCH_PHYS_VIRT && !NEED_MACH_MEMORY_H +- default DRAM_BASE if !MMU ++ default 0x0 + help + Please provide the physical address corresponding to the + location of main memory in your system. diff --git a/with-linux-3.2/series b/with-linux-3.2/series new file mode 100644 index 0000000..de97207 --- /dev/null +++ b/with-linux-3.2/series @@ -0,0 +1,7 @@ +mvsdio-1-2.6.30.patch +mvsdio-2.patch +mvsdio-3.patch +linux-3.0-SDIO-micro-AP.patch +0002-Driver-for-Marvell-Libertas-8688-SDIO-micro-AP-suppo-3.2.patch +linux-3.0.4-LIBERTAS-WEXT_PRIV.patch +phys-virt.diff diff --git a/with-linux-3.4/0002-Driver-for-Marvell-Libertas-8688-SDIO-micro-AP-suppo-3.2.patch b/with-linux-3.4/0002-Driver-for-Marvell-Libertas-8688-SDIO-micro-AP-suppo-3.2.patch deleted file mode 100644 index d725ef3..0000000 --- a/with-linux-3.4/0002-Driver-for-Marvell-Libertas-8688-SDIO-micro-AP-suppo-3.2.patch +++ /dev/null @@ -1,31 +0,0 @@ ---- ./drivers/net/wireless/libertas_uap/uap_main.c.orig 2012-01-05 02:04:22.082318156 -0700 -+++ ./drivers/net/wireless/libertas_uap/uap_main.c 2012-01-05 02:05:50.161341323 -0700 -@@ -1322,20 +1322,6 @@ uap_set_mac_address(struct net_device *d - } - - /** -- * @brief This function sets multicast addresses to firmware -- * -- * @param dev A pointer to net_device structure -- * @return n/a -- */ --static void --uap_set_multicast_list(struct net_device *dev) --{ -- ENTER(); --#warning uap_set_multicast_list not implemented. Expect problems with IPv6. -- LEAVE(); --} -- --/** - * @brief This function handles the timeout of packet - * transmission - * -@@ -1558,7 +1544,6 @@ static const struct net_device_ops uap_n - .ndo_set_mac_address = uap_set_mac_address, - .ndo_tx_timeout = uap_tx_timeout, - .ndo_get_stats = uap_get_stats, -- .ndo_set_multicast_list = uap_set_multicast_list, - }; - #endif - diff --git a/with-linux-3.4/dreamplug-3.4.0.patch b/with-linux-3.4/dreamplug-3.4.0.patch deleted file mode 100644 index 8840d61..0000000 --- a/with-linux-3.4/dreamplug-3.4.0.patch +++ /dev/null @@ -1,107 +0,0 @@ -Index: linux-3.4/arch/arm/mach-kirkwood/Kconfig -=================================================================== ---- linux-3.4.orig/arch/arm/mach-kirkwood/Kconfig 2012-05-27 17:28:53.529328624 -0300 -+++ linux-3.4/arch/arm/mach-kirkwood/Kconfig 2012-05-27 17:28:56.329418105 -0300 -@@ -44,6 +44,12 @@ - Say 'Y' here if you want your kernel to support the - Marvell GuruPlug Reference Board. - -+config MACH_DREAMPLUG -+ bool "Marvell DreamPlug Reference Board" -+ help -+ Say 'Y' here if you want your kernel to support the -+ Marvell DreamPlug Reference Board. -+ - config ARCH_KIRKWOOD_DT - bool "Marvell Kirkwood Flattened Device Tree" - select USE_OF -Index: linux-3.4/arch/arm/mach-kirkwood/Makefile -=================================================================== ---- linux-3.4.orig/arch/arm/mach-kirkwood/Makefile 2012-05-27 17:28:53.599330861 -0300 -+++ linux-3.4/arch/arm/mach-kirkwood/Makefile 2012-05-27 17:28:56.329418105 -0300 -@@ -7,6 +7,7 @@ - obj-$(CONFIG_MACH_SHEEVAPLUG) += sheevaplug-setup.o - obj-$(CONFIG_MACH_ESATA_SHEEVAPLUG) += sheevaplug-setup.o - obj-$(CONFIG_MACH_GURUPLUG) += guruplug-setup.o -+obj-$(CONFIG_MACH_DREAMPLUG) += board-dreamplug.o - obj-$(CONFIG_MACH_DOCKSTAR) += dockstar-setup.o - obj-$(CONFIG_MACH_TS219) += ts219-setup.o tsx1x-common.o - obj-$(CONFIG_MACH_TS41X) += ts41x-setup.o tsx1x-common.o -Index: linux-3.4/arch/arm/mach-kirkwood/board-dreamplug.c -=================================================================== ---- linux-3.4.orig/arch/arm/mach-kirkwood/board-dreamplug.c 2012-05-27 17:28:53.479327026 -0300 -+++ linux-3.4/arch/arm/mach-kirkwood/board-dreamplug.c 2012-05-27 17:28:56.329418105 -0300 -@@ -48,11 +48,13 @@ - .size = SZ_64K, - .offset = SZ_512K + SZ_512K, - }, -+#ifdef CONFIG_MACH_DREAMPLUG_DT - { - .name = "dtb", - .size = SZ_64K, - .offset = SZ_512K + SZ_512K + SZ_512K, - }, -+#endif - }; - - static const struct flash_platform_data dreamplug_spi_slave_data = { -@@ -136,8 +138,16 @@ - /* - * Basic setup. Needs to be called early. - */ -+#ifdef CONFIG_MACH_DREAMPLUG -+ kirkwood_init(); -+#endif -+ - kirkwood_mpp_conf(dreamplug_mpp_config); - -+#ifdef CONFIG_MACH_DREAMPLUG -+ kirkwood_uart0_init(); -+#endif -+ - spi_register_board_info(dreamplug_spi_slave_info, - ARRAY_SIZE(dreamplug_spi_slave_info)); - kirkwood_spi_init(); -@@ -150,3 +160,16 @@ - - platform_device_register(&dreamplug_leds); - } -+ -+#ifdef CONFIG_MACH_DREAMPLUG -+MACHINE_START(DREAMPLUG, "Marvell DreamPlug Reference Board") -+ /* Maintainer: ? */ -+ .map_io = kirkwood_map_io, -+ .init_early = kirkwood_init_early, -+ .init_irq = kirkwood_init_irq, -+ .timer = &kirkwood_timer, -+ .init_machine = dreamplug_init, -+ .restart = kirkwood_restart, -+ .atag_offset = 0x100, -+MACHINE_END -+#endif -Index: linux-3.4/arch/arm/tools/mach-types -=================================================================== ---- linux-3.4.orig/arch/arm/tools/mach-types 2012-05-27 17:28:53.429325427 -0300 -+++ linux-3.4/arch/arm/tools/mach-types 2012-05-27 17:28:56.339418425 -0300 -@@ -845,7 +845,7 @@ - mx51_ivy MACH_MX51_IVY MX51_IVY 3547 - mx51_lvd MACH_MX51_LVD MX51_LVD 3548 - omap3_wiser2 MACH_OMAP3_WISER2 OMAP3_WISER2 3549 --dreamplug MACH_DREAMPLUG DREAMPLUG 3550 -+dreamplug MACH_DREAMPLUG DREAMPLUG 2659 - cobas_c_111 MACH_COBAS_C_111 COBAS_C_111 3551 - cobas_u_411 MACH_COBAS_U_411 COBAS_U_411 3552 - hssd MACH_HSSD HSSD 3553 -Index: linux-3.4/arch/arm/mach-kirkwood/common.h -=================================================================== ---- linux-3.4.orig/arch/arm/mach-kirkwood/common.h 2012-05-27 17:29:00.629555522 -0300 -+++ linux-3.4/arch/arm/mach-kirkwood/common.h 2012-05-27 17:36:06.263156553 -0300 -@@ -52,7 +52,7 @@ - void kirkwood_restart(char, const char *); - - /* board init functions for boards not fully converted to fdt */ --#ifdef CONFIG_MACH_DREAMPLUG_DT -+#if defined CONFIG_MACH_DREAMPLUG_DT || defined CONFIG_MACH_DREAMPLUG - void dreamplug_init(void); - #else - static inline void dreamplug_init(void) {}; diff --git a/with-linux-3.4/linux-3.0-SDIO-micro-AP.patch b/with-linux-3.4/linux-3.0-SDIO-micro-AP.patch deleted file mode 100644 index 9998a51..0000000 --- a/with-linux-3.4/linux-3.0-SDIO-micro-AP.patch +++ /dev/null @@ -1,5111 +0,0 @@ -diff -Naupr linux-2.6.37/drivers/net/wireless/Kconfig linux-2.6.37-new/drivers/net/wireless/Kconfig ---- linux-2.6.37/drivers/net/wireless/Kconfig 2011-01-04 17:50:19.000000000 -0700 -+++ linux-2.6.37-new/drivers/net/wireless/Kconfig 2011-01-08 06:01:04.034836160 -0700 -@@ -51,6 +51,12 @@ config LIBERTAS_THINFIRM_USB - ---help--- - A driver for Marvell Libertas 8388 USB devices using thinfirm. - -+config LIBERTAS_UAP -+ tristate "Marvell Libertas 8688 micro-AP support" -+ depends on LIBERTAS && MMC -+ ---help--- -+ A driver for Marvell Libertas 8688 SDIO micro-AP support. -+ - config AIRO - tristate "Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards" - depends on ISA_DMA_API && (PCI || BROKEN) -diff -Naupr linux-2.6.37/drivers/net/wireless/Makefile linux-2.6.37-new/drivers/net/wireless/Makefile ---- linux-2.6.37/drivers/net/wireless/Makefile 2011-01-04 17:50:19.000000000 -0700 -+++ linux-2.6.37-new/drivers/net/wireless/Makefile 2011-01-08 06:01:04.034836160 -0700 -@@ -36,6 +36,8 @@ obj-$(CONFIG_LIBERTAS) += libertas/ - - obj-$(CONFIG_LIBERTAS_THINFIRM) += libertas_tf/ - -+obj-$(CONFIG_LIBERTAS_UAP) += libertas_uap/ -+ - obj-$(CONFIG_ADM8211) += adm8211.o - - obj-$(CONFIG_MWL8K) += mwl8k.o -diff -Naupr linux-2.6.37/drivers/net/wireless/libertas_uap/Makefile linux-2.6.37-new/drivers/net/wireless/libertas_uap/Makefile ---- linux-2.6.37/drivers/net/wireless/libertas_uap/Makefile 1969-12-31 17:00:00.000000000 -0700 -+++ linux-2.6.37-new/drivers/net/wireless/libertas_uap/Makefile 2011-01-08 06:01:04.036836021 -0700 -@@ -0,0 +1,6 @@ -+obj-$(CONFIG_LIBERTAS_UAP) += uap8xxx.o -+ -+uap8xxx-y += uap_main.o uap_sdio_mmc.o -+uap8xxx-$(CONFIG_PROC_FS) += uap_proc.o uap_debug.o -+ -+EXTRA_CFLAGS += -DFPNUM='"52"' -DPXA3XX_DMA_ALIGN -DDEBUG_LEVEL1 -diff -Naupr linux-2.6.37/drivers/net/wireless/libertas_uap/uap_debug.c linux-2.6.37-new/drivers/net/wireless/libertas_uap/uap_debug.c ---- linux-2.6.37/drivers/net/wireless/libertas_uap/uap_debug.c 1969-12-31 17:00:00.000000000 -0700 -+++ linux-2.6.37-new/drivers/net/wireless/libertas_uap/uap_debug.c 2011-01-08 06:01:04.038835884 -0700 -@@ -0,0 +1,261 @@ -+/** @file uap_debug.c -+ * @brief This file contains functions for debug proc file. -+ * -+ * Copyright (C) 2008-2009, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available along with the File in the gpl.txt file or by writing to -+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ * -+ */ -+#ifdef CONFIG_PROC_FS -+#include "uap_headers.h" -+ -+/******************************************************** -+ Local Variables -+********************************************************/ -+ -+#define item_size(n) (sizeof ((uap_adapter *)0)->n) -+#define item_addr(n) ((u32) &((uap_adapter *)0)->n) -+ -+#define item_dbg_size(n) (sizeof (((uap_adapter *)0)->dbg.n)) -+#define item_dbg_addr(n) ((u32) &(((uap_adapter *)0)->dbg.n)) -+ -+#define item_dev_size(n) (sizeof ((uap_dev_t *)0)->n) -+#define item_dev_addr(n) ((u32) &((uap_dev_t *)0)->n) -+ -+/** MicroAp device offset */ -+#define OFFSET_UAP_DEV 0x01 -+/** Bluetooth adapter offset */ -+#define OFFSET_UAP_ADAPTER 0x02 -+ -+struct debug_data -+{ -+ /** Name */ -+ char name[32]; -+ /** Size */ -+ u32 size; -+ /** Address */ -+ u32 addr; -+ /** Offset */ -+ u32 offset; -+ /** Flag */ -+ u32 flag; -+}; -+ -+/* To debug any member of uap_adapter, simply add one line here. -+ */ -+static struct debug_data items[] = { -+ {"cmd_sent", item_dev_size(cmd_sent), 0, item_dev_addr(cmd_sent), -+ OFFSET_UAP_DEV}, -+ {"data_sent", item_dev_size(data_sent), 0, item_dev_addr(data_sent), -+ OFFSET_UAP_DEV}, -+ {"IntCounter", item_size(IntCounter), 0, item_addr(IntCounter), -+ OFFSET_UAP_ADAPTER}, -+ {"cmd_pending", item_size(cmd_pending), 0, item_addr(cmd_pending), -+ OFFSET_UAP_ADAPTER}, -+ {"num_cmd_h2c_fail", item_dbg_size(num_cmd_host_to_card_failure), 0, -+ item_dbg_addr(num_cmd_host_to_card_failure), OFFSET_UAP_ADAPTER}, -+ {"num_tx_h2c_fail", item_dbg_size(num_tx_host_to_card_failure), 0, -+ item_dbg_addr(num_tx_host_to_card_failure), OFFSET_UAP_ADAPTER}, -+ {"psmode", item_size(psmode), 0, item_addr(psmode), OFFSET_UAP_ADAPTER}, -+ {"ps_state", item_size(ps_state), 0, item_addr(ps_state), -+ OFFSET_UAP_ADAPTER}, -+#ifdef DEBUG_LEVEL1 -+ {"drvdbg", sizeof(drvdbg), (u32) & drvdbg, 0, 0} -+#endif -+}; -+ -+static int num_of_items = sizeof(items) / sizeof(items[0]); -+ -+/******************************************************** -+ Global Variables -+********************************************************/ -+ -+/******************************************************** -+ Local Functions -+********************************************************/ -+/** -+ * @brief proc read function -+ * -+ * @param page pointer to buffer -+ * @param s read data starting position -+ * @param off offset -+ * @param cnt counter -+ * @param eof end of file flag -+ * @param data data to output -+ * @return number of output data -+ */ -+static int -+uap_debug_read(char *page, char **s, off_t off, int cnt, int *eof, void *data) -+{ -+ int val = 0; -+ char *p = page; -+ int i; -+ -+ struct debug_data *d = (struct debug_data *) data; -+ -+ if (MODULE_GET == 0) -+ return UAP_STATUS_FAILURE; -+ -+ for (i = 0; i < num_of_items; i++) { -+ if (d[i].size == 1) -+ val = *((u8 *) d[i].addr); -+ else if (d[i].size == 2) -+ val = *((u16 *) d[i].addr); -+ else if (d[i].size == 4) -+ val = *((u32 *) d[i].addr); -+ -+ p += sprintf(p, "%s=%d\n", d[i].name, val); -+ } -+ MODULE_PUT; -+ return p - page; -+} -+ -+/** -+ * @brief proc write function -+ * -+ * @param f file pointer -+ * @param buf pointer to data buffer -+ * @param cnt data number to write -+ * @param data data to write -+ * @return number of data -+ */ -+static int -+uap_debug_write(struct file *f, const char *buf, unsigned long cnt, void *data) -+{ -+ int r, i; -+ char *pdata; -+ char *p; -+ char *p0; -+ char *p1; -+ char *p2; -+ struct debug_data *d = (struct debug_data *) data; -+ -+ if (MODULE_GET == 0) -+ return UAP_STATUS_FAILURE; -+ -+ pdata = (char *) kmalloc(cnt, GFP_KERNEL); -+ if (pdata == NULL) { -+ MODULE_PUT; -+ return 0; -+ } -+ -+ if (copy_from_user(pdata, buf, cnt)) { -+ PRINTM(INFO, "Copy from user failed\n"); -+ kfree(pdata); -+ MODULE_PUT; -+ return 0; -+ } -+ -+ p0 = pdata; -+ for (i = 0; i < num_of_items; i++) { -+ do { -+ p = strstr(p0, d[i].name); -+ if (p == NULL) -+ break; -+ p1 = strchr(p, '\n'); -+ if (p1 == NULL) -+ break; -+ p0 = p1++; -+ p2 = strchr(p, '='); -+ if (!p2) -+ break; -+ p2++; -+ r = string_to_number(p2); -+ if (d[i].size == 1) -+ *((u8 *) d[i].addr) = (u8) r; -+ else if (d[i].size == 2) -+ *((u16 *) d[i].addr) = (u16) r; -+ else if (d[i].size == 4) -+ *((u32 *) d[i].addr) = (u32) r; -+ break; -+ } while (TRUE); -+ } -+ kfree(pdata); -+#ifdef DEBUG_LEVEL1 -+ printk(KERN_ALERT "drvdbg = 0x%x\n", drvdbg); -+ printk(KERN_ALERT "INFO (%08lx) %s\n", DBG_INFO, -+ (drvdbg & DBG_INFO) ? "X" : ""); -+ printk(KERN_ALERT "WARN (%08lx) %s\n", DBG_WARN, -+ (drvdbg & DBG_WARN) ? "X" : ""); -+ printk(KERN_ALERT "ENTRY (%08lx) %s\n", DBG_ENTRY, -+ (drvdbg & DBG_ENTRY) ? "X" : ""); -+ printk(KERN_ALERT "CMD_D (%08lx) %s\n", DBG_CMD_D, -+ (drvdbg & DBG_CMD_D) ? "X" : ""); -+ printk(KERN_ALERT "DAT_D (%08lx) %s\n", DBG_DAT_D, -+ (drvdbg & DBG_DAT_D) ? "X" : ""); -+ printk(KERN_ALERT "CMND (%08lx) %s\n", DBG_CMND, -+ (drvdbg & DBG_CMND) ? "X" : ""); -+ printk(KERN_ALERT "DATA (%08lx) %s\n", DBG_DATA, -+ (drvdbg & DBG_DATA) ? "X" : ""); -+ printk(KERN_ALERT "ERROR (%08lx) %s\n", DBG_ERROR, -+ (drvdbg & DBG_ERROR) ? "X" : ""); -+ printk(KERN_ALERT "FATAL (%08lx) %s\n", DBG_FATAL, -+ (drvdbg & DBG_FATAL) ? "X" : ""); -+ printk(KERN_ALERT "MSG (%08lx) %s\n", DBG_MSG, -+ (drvdbg & DBG_MSG) ? "X" : ""); -+#endif -+ MODULE_PUT; -+ return cnt; -+} -+ -+/******************************************************** -+ Global Functions -+********************************************************/ -+/** -+ * @brief create debug proc file -+ * -+ * @param priv pointer uap_private -+ * @param dev pointer net_device -+ * @return N/A -+ */ -+void -+uap_debug_entry(uap_private * priv, struct net_device *dev) -+{ -+ int i; -+ struct proc_dir_entry *r; -+ -+ if (priv->proc_entry == NULL) -+ return; -+ -+ for (i = 0; i < num_of_items; i++) { -+ if (items[i].flag & OFFSET_UAP_ADAPTER) -+ items[i].addr = items[i].offset + (u32) priv->adapter; -+ if (items[i].flag & OFFSET_UAP_DEV) -+ items[i].addr = items[i].offset + (u32) & priv->uap_dev; -+ } -+ r = create_proc_entry("debug", 0644, priv->proc_entry); -+ if (r == NULL) -+ return; -+ -+ r->data = &items[0]; -+ r->read_proc = uap_debug_read; -+ r->write_proc = uap_debug_write; -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) -+ r->owner = THIS_MODULE; -+#endif -+} -+ -+/** -+ * @brief remove proc file -+ * -+ * @param priv pointer uap_private -+ * @return N/A -+ */ -+void -+uap_debug_remove(uap_private * priv) -+{ -+ remove_proc_entry("debug", priv->proc_entry); -+} -+ -+#endif -diff -Naupr linux-2.6.37/drivers/net/wireless/libertas_uap/uap_drv.h linux-2.6.37-new/drivers/net/wireless/libertas_uap/uap_drv.h ---- linux-2.6.37/drivers/net/wireless/libertas_uap/uap_drv.h 1969-12-31 17:00:00.000000000 -0700 -+++ linux-2.6.37-new/drivers/net/wireless/libertas_uap/uap_drv.h 2011-06-26 00:15:04.040835746 -0700 -@@ -0,0 +1,667 @@ -+/** @file uap_drv.h -+ * @brief This file contains Linux OS related definitions and -+ * declarations, uAP driver -+ * -+ * Copyright (C) 2008-2009, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available along with the File in the gpl.txt file or by writing to -+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ * -+ */ -+ -+#ifndef _UAP_DRV_H -+#define _UAP_DRV_H -+ -+/** Driver release version */ -+#define DRIVER_VERSION "26146" -+ -+/** True */ -+#ifndef TRUE -+#define TRUE 1 -+#endif -+/** False */ -+#ifndef FALSE -+#define FALSE 0 -+#endif -+ -+/** Bit definitions */ -+#ifndef BIT -+#define BIT(x) (1UL << (x)) -+#endif -+ -+/** Dma addresses are 32-bits wide. */ -+#ifndef __ATTRIB_ALIGN__ -+#define __ATTRIB_ALIGN__ __attribute__((aligned(4))) -+#endif -+ -+/** attribute pack */ -+#ifndef __ATTRIB_PACK__ -+#define __ATTRIB_PACK__ __attribute__ ((packed)) -+#endif -+ -+/** Debug Macro definition*/ -+#ifdef DEBUG_LEVEL1 -+ -+extern u32 drvdbg; -+ -+/** Debug message control bit definition for drvdbg */ -+/** Debug message */ -+#define DBG_MSG BIT(0) -+/** Debug fatal message */ -+#define DBG_FATAL BIT(1) -+/** Debug error message */ -+#define DBG_ERROR BIT(2) -+/** Debug data message */ -+#define DBG_DATA BIT(3) -+/** Debug command message */ -+#define DBG_CMND BIT(4) -+ -+/** Debug data */ -+#define DBG_DAT_D BIT(16) -+/** Debug command */ -+#define DBG_CMD_D BIT(17) -+ -+/** Debug entry */ -+#define DBG_ENTRY BIT(28) -+/** Debug warning */ -+#define DBG_WARN BIT(29) -+/** Debug info */ -+#define DBG_INFO BIT(30) -+ -+/** Print info */ -+#define PRINTM_INFO(msg...) {if (drvdbg & DBG_INFO) printk(KERN_DEBUG msg);} -+/** Print warn message */ -+#define PRINTM_WARN(msg...) {if (drvdbg & DBG_WARN) printk(KERN_DEBUG msg);} -+/** Print entry */ -+#define PRINTM_ENTRY(msg...) {if (drvdbg & DBG_ENTRY) printk(KERN_DEBUG msg);} -+/** Print cmd_d */ -+#define PRINTM_CMD_D(msg...) {if (drvdbg & DBG_CMD_D) printk(KERN_DEBUG msg);} -+/** Print data_d */ -+#define PRINTM_DAT_D(msg...) {if (drvdbg & DBG_DAT_D) printk(KERN_DEBUG msg);} -+/** Print command */ -+#define PRINTM_CMND(msg...) {if (drvdbg & DBG_CMND) printk(KERN_DEBUG msg);} -+/** Print data */ -+#define PRINTM_DATA(msg...) {if (drvdbg & DBG_DATA) printk(KERN_DEBUG msg);} -+/** Print error message */ -+#define PRINTM_ERROR(msg...) {if (drvdbg & DBG_ERROR) printk(KERN_DEBUG msg);} -+/** Print fatal message */ -+#define PRINTM_FATAL(msg...) {if (drvdbg & DBG_FATAL) printk(KERN_DEBUG msg);} -+/** Print message */ -+#define PRINTM_MSG(msg...) {if (drvdbg & DBG_MSG) printk(KERN_ALERT msg);} -+/** Print level */ -+#define PRINTM(level,msg...) PRINTM_##level(msg) -+ -+#else -+ -+#define PRINTM(level,msg...) do {} while (0) -+ -+#endif /* DEBUG_LEVEL1 */ -+ -+/** Wait until a condition becomes true */ -+#define ASSERT(cond) \ -+do { \ -+ if (!(cond)) \ -+ PRINTM(INFO, "ASSERT: %s, %s:%i\n", \ -+ __FUNCTION__, __FILE__, __LINE__); \ -+} while(0) -+ -+/** Log enrty point for debugging */ -+#define ENTER() PRINTM(ENTRY, "Enter: %s, %s:%i\n", __FUNCTION__, \ -+ __FILE__, __LINE__) -+/** Log exit point for debugging */ -+#define LEAVE() PRINTM(ENTRY, "Leave: %s, %s:%i\n", __FUNCTION__, \ -+ __FILE__, __LINE__) -+ -+#ifdef DEBUG_LEVEL1 -+/** Dump buffer length */ -+#define DBG_DUMP_BUF_LEN 64 -+/** Maximum dump per line */ -+#define MAX_DUMP_PER_LINE 16 -+/** Data dump length */ -+#define DATA_DUMP_LEN 32 -+ -+static inline void -+hexdump(char *prompt, u8 * buf, int len) -+{ -+ int i; -+ char dbgdumpbuf[DBG_DUMP_BUF_LEN]; -+ char *ptr = dbgdumpbuf; -+ -+ printk(KERN_DEBUG "%s:\n", prompt); -+ for (i = 1; i <= len; i++) { -+ ptr += sprintf(ptr, "%02x ", *buf); -+ buf++; -+ if (i % MAX_DUMP_PER_LINE == 0) { -+ *ptr = 0; -+ printk(KERN_DEBUG "%s\n", dbgdumpbuf); -+ ptr = dbgdumpbuf; -+ } -+ } -+ if (len % MAX_DUMP_PER_LINE) { -+ *ptr = 0; -+ printk(KERN_DEBUG "%s\n", dbgdumpbuf); -+ } -+} -+ -+/** Debug command */ -+#define DBG_HEXDUMP_CMD_D(x,y,z) {if (drvdbg & DBG_CMD_D) hexdump(x,y,z);} -+/** Debug data */ -+#define DBG_HEXDUMP_DAT_D(x,y,z) {if (drvdbg & DBG_DAT_D) hexdump(x,y,z);} -+/** Debug hexdump */ -+#define DBG_HEXDUMP(level,x,y,z) DBG_HEXDUMP_##level(x,y,z) -+/** hexdump */ -+#define HEXDUMP(x,y,z) {if (drvdbg & DBG_INFO) hexdump(x,y,z);} -+#else -+/** Do nothing since debugging is not turned on */ -+#define DBG_HEXDUMP(level,x,y,z) do {} while (0) -+/** Do nothing since debugging is not turned on */ -+#define HEXDUMP(x,y,z) do {} while (0) -+#endif -+ -+/** -+ * Typedefs -+ */ -+/** Unsigned char */ -+typedef u8 BOOLEAN; -+ -+/* -+ * OS macro definitions -+ */ -+/** OS macro to get time */ -+#define os_time_get() jiffies -+ -+/** OS macro to update transfer start time */ -+#define UpdateTransStart(dev) { \ -+ dev->trans_start = jiffies; \ -+} -+ -+/** Try to get a reference to the module */ -+#define MODULE_GET try_module_get(THIS_MODULE) -+/** Decrease module reference count */ -+#define MODULE_PUT module_put(THIS_MODULE) -+ -+/** OS macro to initialize semaphore */ -+#define OS_INIT_SEMAPHORE(x) sema_init(x,1) -+/** OS macro to acquire blocking semaphore */ -+#define OS_ACQ_SEMAPHORE_BLOCK(x) down_interruptible(x) -+/** OS macro to acquire non-blocking semaphore */ -+#define OS_ACQ_SEMAPHORE_NOBLOCK(x) down_trylock(x) -+/** OS macro to release semaphore */ -+#define OS_REL_SEMAPHORE(x) up(x) -+ -+static inline void -+os_sched_timeout(u32 millisec) -+{ -+ set_current_state(TASK_INTERRUPTIBLE); -+ schedule_timeout((millisec * HZ) / 1000); -+} -+ -+/** Maximum size of ethernet packet */ -+#define MRVDRV_MAXIMUM_ETH_PACKET_SIZE 1514 -+ -+/** Maximum size of multicast list */ -+#define MRVDRV_MAX_MULTICAST_LIST_SIZE 32 -+ -+/** Find minimum */ -+#ifndef MIN -+#define MIN(a,b) ((a) < (b) ? (a) : (b)) -+#endif -+ -+/** Find maximum */ -+#ifndef MAX -+#define MAX(a,b) ((a) > (b) ? (a) : (b)) -+#endif -+ -+/** Find number of elements */ -+#ifndef NELEMENTS -+#define NELEMENTS(x) (sizeof(x)/sizeof(x[0])) -+#endif -+ -+/** Buffer Constants */ -+ -+/** Size of command buffer */ -+#define MRVDRV_SIZE_OF_CMD_BUFFER (2 * 1024) -+ -+/** Length of device length */ -+#define DEV_NAME_LEN 32 -+ -+/** Length of ethernet address */ -+#ifndef ETH_ALEN -+#define ETH_ALEN 6 -+#endif -+ -+/** Default watchdog timeout */ -+#define MRVDRV_DEFAULT_WATCHDOG_TIMEOUT (2 * HZ) -+ -+/** Success */ -+#define UAP_STATUS_SUCCESS (0) -+/** Failure */ -+#define UAP_STATUS_FAILURE (-1) -+/** Not accepted */ -+#define UAP_STATUS_NOT_ACCEPTED (-2) -+ -+/** Max loop count (* 100ms) for waiting device ready at init time */ -+#define MAX_WAIT_DEVICE_READY_COUNT 50 -+ -+/** Tx high watermark. Stop Tx queue after this is crossed */ -+#define TX_HIGH_WATERMARK 4 -+/** Tx low watermark. Restart Tx queue after this is crossed */ -+#define TX_LOW_WATERMARK 2 -+ -+/** Netlink protocol number */ -+#define NETLINK_MARVELL (MAX_LINKS - 1) -+/** Netlink maximum payload size */ -+#define NL_MAX_PAYLOAD 1024 -+/** Netlink multicast group number */ -+#define NL_MULTICAST_GROUP 1 -+ -+/** 20 seconds */ -+#define MRVDRV_TIMER_20S 20000 -+ -+/** Host Command option for wait till Send */ -+#define HostCmd_OPTION_WAITFORSEND 0x0001 -+/** Host Command option for wait for RSP */ -+#define HostCmd_OPTION_WAITFORRSP 0x0002 -+/** Host Command option for wait for RSP or Timeout */ -+#define HostCmd_OPTION_WAITFORRSP_TIMEOUT 0x0003 -+/** Host Command option for wait for RSP of sleep confirm */ -+#define HostCmd_OPTION_WAITFORRSP_SLEEPCONFIRM 0x0004 -+ -+/** Sleep until a condition gets true or a timeout elapses */ -+#define os_wait_interruptible_timeout(waitq, cond, timeout) \ -+ wait_event_interruptible_timeout(waitq, cond, ((timeout) * HZ / 1000)) -+ -+/** Private command ID to Host command */ -+#define UAPHOSTCMD (SIOCDEVPRIVATE + 1) -+ -+/** Private command ID to Power Mode */ -+#define UAP_POWER_MODE (SIOCDEVPRIVATE + 3) -+/** sleep_param */ -+typedef struct _ps_sleep_param -+{ -+ /** control bitmap */ -+ u32 ctrl_bitmap; -+ /** minimum sleep period (micro second) */ -+ u32 min_sleep; -+ /** maximum sleep period (micro second) */ -+ u32 max_sleep; -+} ps_sleep_param; -+ -+/** inactivity sleep_param */ -+typedef struct _inact_sleep_param -+{ -+ /** inactivity timeout (micro second) */ -+ u32 inactivity_to; -+ /** miniumu awake period (micro second) */ -+ u32 min_awake; -+ /** maximum awake period (micro second) */ -+ u32 max_awake; -+} inact_sleep_param; -+ -+/** flag for ps mode */ -+#define PS_FLAG_PS_MODE 1 -+/** flag for sleep param */ -+#define PS_FLAG_SLEEP_PARAM 2 -+/** flag for inactivity sleep param */ -+#define PS_FLAG_INACT_SLEEP_PARAM 4 -+ -+/** Disable power mode */ -+#define PS_MODE_DISABLE 0 -+/** Enable periodic dtim ps */ -+#define PS_MODE_PERIODIC_DTIM 1 -+/** Enable inactivity ps */ -+#define PS_MODE_INACTIVITY 2 -+ -+/** sleep parameter */ -+#define SLEEP_PARAMETER 1 -+/** inactivity sleep parameter */ -+#define INACTIVITY_SLEEP_PARAMETER 2 -+/** ps_mgmt */ -+typedef struct _ps_mgmt -+{ -+ /** flags for valid field */ -+ u16 flags; -+ /** power mode */ -+ u16 ps_mode; -+ /** sleep param */ -+ ps_sleep_param sleep_param; -+ /** inactivity sleep param */ -+ inact_sleep_param inact_param; -+} ps_mgmt; -+ -+/** Semaphore structure */ -+typedef struct semaphore SEMAPHORE; -+ -+/** Global Varibale Declaration */ -+/** Private data structure of the device */ -+typedef struct _uap_private uap_private; -+/** Adapter data structure of the device */ -+typedef struct _uap_adapter uap_adapter; -+/** private structure */ -+extern uap_private *uappriv; -+ -+/** ENUM definition*/ -+ -+/** Hardware status codes */ -+typedef enum _HARDWARE_STATUS -+{ -+ HWReady, -+ HWInitializing, -+ HWReset, -+ HWClosing, -+ HWNotReady -+} HARDWARE_STATUS; -+ -+/** info for debug purpose */ -+typedef struct _uap_dbg -+{ -+ /** Number of host to card command failures */ -+ u32 num_cmd_host_to_card_failure; -+ /** Number of host to card Tx failures */ -+ u32 num_tx_host_to_card_failure; -+} uap_dbg; -+ -+/** Set thread state */ -+#define OS_SET_THREAD_STATE(x) set_current_state(x) -+ -+typedef struct -+{ -+ /** Task */ -+ struct task_struct *task; -+ /** Queue */ -+ wait_queue_head_t waitQ; -+ /** PID */ -+ pid_t pid; -+ /** Private structure */ -+ void *priv; -+} uap_thread; -+ -+static inline void -+uap_activate_thread(uap_thread * thr) -+{ -+ /** Record the thread pid */ -+ thr->pid = current->pid; -+ -+ /** Initialize the wait queue */ -+ init_waitqueue_head(&thr->waitQ); -+} -+ -+static inline void -+uap_deactivate_thread(uap_thread * thr) -+{ -+ thr->pid = 0; -+ return; -+} -+ -+static inline void -+uap_create_thread(int (*uapfunc) (void *), uap_thread * thr, char *name) -+{ -+ thr->task = kthread_run(uapfunc, thr, "%s", name); -+} -+ -+static inline int -+uap_terminate_thread(uap_thread * thr) -+{ -+ /* Check if the thread is active or not */ -+ if (!thr->pid) -+ return -1; -+ kthread_stop(thr->task); -+ return 0; -+} -+ -+/** Data structure for the Marvell uAP device */ -+typedef struct _uap_dev -+{ -+ /** device name */ -+ char name[DEV_NAME_LEN]; -+ /** card pointer */ -+ void *card; -+ /** IO port */ -+ u32 ioport; -+ /** Rx unit */ -+ u8 rx_unit; -+ /** Data sent: -+ TRUE - Data is sent to fw, no Tx Done received -+ FALSE - Tx done received for previous Tx */ -+ BOOLEAN data_sent; -+ /** CMD sent: -+ TRUE - CMD is sent to fw, no CMD Done received -+ FALSE - CMD done received for previous CMD */ -+ BOOLEAN cmd_sent; -+ /** netdev pointer */ -+ struct net_device *netdev; -+} uap_dev_t, *puap_dev_t; -+ -+/** Private structure for the MV device */ -+struct _uap_private -+{ -+ /** Device open */ -+ int open; -+ -+ /** Device adapter structure */ -+ uap_adapter *adapter; -+ /** Device structure */ -+ uap_dev_t uap_dev; -+ -+ /** Net device statistics structure */ -+ struct net_device_stats stats; -+ -+ /** Number of Tx timeouts */ -+ u32 num_tx_timeout; -+ -+ /** Media connection status */ -+ BOOLEAN MediaConnected; -+ -+#ifdef CONFIG_PROC_FS -+ struct proc_dir_entry *proc_uap; -+ struct proc_dir_entry *proc_entry; -+#endif /* CONFIG_PROC_FS */ -+ -+ /** Firmware helper */ -+ const struct firmware *fw_helper; -+ /** Firmware */ -+ const struct firmware *firmware; -+ /** Hotplug device */ -+ struct device *hotplug_device; -+ /** thread to service interrupts */ -+ uap_thread MainThread; -+ /** Driver lock */ -+ spinlock_t driver_lock; -+ /** Driver lock flags */ -+ ulong driver_flags; -+ -+}; -+ -+/** PS_CMD_ConfirmSleep */ -+typedef struct _PS_CMD_ConfirmSleep -+{ -+ /** SDIO Length */ -+ u16 SDLen; -+ /** SDIO Type */ -+ u16 SDType; -+ /** Command */ -+ u16 Command; -+ /** Size */ -+ u16 Size; -+ /** Sequence number */ -+ u16 SeqNum; -+ /** Result */ -+ u16 Result; -+} __ATTRIB_PACK__ PS_CMD_ConfirmSleep, *PPS_CMD_ConfirmSleep; -+ -+/** Wlan Adapter data structure*/ -+struct _uap_adapter -+{ -+ /** Power save confirm sleep command */ -+ PS_CMD_ConfirmSleep PSConfirmSleep; -+ /** Device status */ -+ HARDWARE_STATUS HardwareStatus; -+ /** Interrupt counter */ -+ u32 IntCounter; -+ /** Tx packet queue */ -+ struct sk_buff_head tx_queue; -+ /** Cmd packet queue */ -+ struct sk_buff_head cmd_queue; -+ /** Command sequence number */ -+ u16 SeqNum; -+ /** Command buffer */ -+ u8 *CmdBuf; -+ /** cmd pending flag */ -+ u8 cmd_pending; -+ /** cmd wait option */ -+ u8 cmd_wait_option; -+ /** Command buffer length */ -+ u32 CmdSize; -+ /** Command wait queue */ -+ wait_queue_head_t cmdwait_q __ATTRIB_ALIGN__; -+ /** Command wait queue state flag */ -+ u8 CmdWaitQWoken; -+ /** PnP support */ -+ BOOLEAN SurpriseRemoved; -+ /** Debug */ -+ uap_dbg dbg; -+ /** Netlink kernel socket */ -+ struct sock *nl_sk; -+ /** Semaphore for CMD */ -+ SEMAPHORE CmdSem; -+ /** Power Save mode */ -+ u8 psmode; -+ /** Power Save state */ -+ u8 ps_state; -+ /** Number of wakeup tries */ -+ u32 WakeupTries; -+}; -+ -+static inline int -+os_upload_rx_packet(uap_private * priv, struct sk_buff *skb) -+{ -+ skb->dev = priv->uap_dev.netdev; -+ skb->protocol = eth_type_trans(skb, priv->uap_dev.netdev); -+ skb->ip_summed = CHECKSUM_UNNECESSARY; -+ if (in_interrupt()) -+ netif_rx(skb); -+ else -+ netif_rx_ni(skb); -+ return 0; -+} -+ -+/* -+ * netif carrier_on/off and start(wake)/stop_queue handling -+ */ -+static inline void -+os_carrier_on(uap_private * priv) -+{ -+ if (!netif_carrier_ok(priv->uap_dev.netdev) && -+ (priv->MediaConnected == TRUE)) { -+ netif_carrier_on(priv->uap_dev.netdev); -+ } -+} -+ -+static inline void -+os_carrier_off(uap_private * priv) -+{ -+ if (netif_carrier_ok(priv->uap_dev.netdev)) { -+ netif_carrier_off(priv->uap_dev.netdev); -+ } -+} -+ -+static inline void -+os_start_queue(uap_private * priv) -+{ -+ if (netif_queue_stopped(priv->uap_dev.netdev) && -+ (priv->MediaConnected == TRUE)) { -+ netif_wake_queue(priv->uap_dev.netdev); -+ } -+} -+ -+static inline void -+os_stop_queue(uap_private * priv) -+{ -+ if (!netif_queue_stopped(priv->uap_dev.netdev)) { -+ netif_stop_queue(priv->uap_dev.netdev); -+ } -+} -+ -+/** Interface specific header */ -+#define INTF_HEADER_LEN 4 -+ -+/** headroom alignment for tx packet */ -+#define HEADER_ALIGNMENT 8 -+ -+/** The number of times to try when polling for status bits */ -+#define MAX_POLL_TRIES 100 -+ -+/** Length of SNAP header */ -+#define MRVDRV_SNAP_HEADER_LEN 8 -+ -+/** Extra length of Tx packet buffer */ -+#define EXTRA_LEN 36 -+ -+/** Buffer size for ethernet Tx packets */ -+#define MRVDRV_ETH_TX_PACKET_BUFFER_SIZE \ -+ (ETH_FRAME_LEN + sizeof(TxPD) + EXTRA_LEN) -+ -+/** Buffer size for ethernet Rx packets */ -+#define MRVDRV_ETH_RX_PACKET_BUFFER_SIZE \ -+ (ETH_FRAME_LEN + sizeof(RxPD) \ -+ + MRVDRV_SNAP_HEADER_LEN + EXTRA_LEN) -+ -+/** Packet type: data, command & event */ -+typedef enum _mv_type -+{ -+ MV_TYPE_DAT = 0, -+ MV_TYPE_CMD = 1, -+ MV_TYPE_EVENT = 3 -+} mv_type; -+ -+/** Disable interrupt */ -+#define OS_INT_DISABLE spin_lock_irqsave(&priv->driver_lock, priv->driver_flags) -+/** Enable interrupt */ -+#define OS_INT_RESTORE spin_unlock_irqrestore(&priv->driver_lock, priv->driver_flags) -+ -+int uap_process_rx_packet(uap_private * priv, struct sk_buff *skb); -+void uap_interrupt(uap_private * priv); -+uap_private *uap_add_card(void *card); -+int uap_remove_card(void *card); -+int uap_process_event(uap_private * priv, u8 * payload, uint len); -+int uap_soft_reset(uap_private * priv); -+int uap_process_sleep_confirm_resp(uap_private * priv, u8 * resp, int resp_len); -+ -+#ifdef CONFIG_PROC_FS -+/** The proc fs interface */ -+void uap_proc_entry(uap_private * priv, struct net_device *dev); -+void uap_proc_remove(uap_private * priv); -+int string_to_number(char *s); -+void uap_debug_entry(uap_private * priv, struct net_device *dev); -+void uap_debug_remove(uap_private * priv); -+#endif /* CONFIG_PROC_FS */ -+ -+int sbi_register(void); -+ -+void sbi_unregister(void); -+int sbi_register_dev(uap_private * priv); -+int sbi_unregister_dev(uap_private * priv); -+int sbi_prog_fw_w_helper(uap_private *); -+ -+int sbi_host_to_card(uap_private * priv, u8 * payload, u16 nb); -+int sbi_enable_host_int(uap_private * priv); -+int sbi_disable_host_int(uap_private * priv); -+ -+int sbi_get_int_status(uap_private * priv, u8 * ireg); -+/** Check firmware status */ -+int sbi_check_fw_status(uap_private *, int); -+int sbi_prog_helper(uap_private *); -+ -+int sbi_wakeup_firmware(uap_private * priv); -+ -+#endif /* _UAP_DRV_H */ -diff -Naupr linux-2.6.37/drivers/net/wireless/libertas_uap/uap_fw.h linux-2.6.37-new/drivers/net/wireless/libertas_uap/uap_fw.h ---- linux-2.6.37/drivers/net/wireless/libertas_uap/uap_fw.h 1969-12-31 17:00:00.000000000 -0700 -+++ linux-2.6.37-new/drivers/net/wireless/libertas_uap/uap_fw.h 2011-01-08 06:01:04.042835607 -0700 -@@ -0,0 +1,359 @@ -+/** @file uap_fw.h -+ * -+ * @brief This file contains firmware specific defines. -+ * -+ * Copyright (C) 2008-2009, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available along with the File in the gpl.txt file or by writing to -+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ * -+ */ -+/******************************************************** -+Change log: -+ 02/26/08: Initial creation -+********************************************************/ -+ -+#ifndef _UAP_FW_H -+#define _UAP_FW_H -+ -+/** uap upload size */ -+#define UAP_UPLD_SIZE 2312 -+/** Packet type Micro AP */ -+#define PKT_TYPE_MICROAP 1 -+/** Packet type client */ -+#define PKT_TYPE_CLIENT 0 -+ -+/** TxPD descriptor */ -+typedef struct _TxPD -+{ -+ /** Bss Type */ -+ u8 BssType; -+ /** Bss num */ -+ u8 BssNum; -+ /** Tx packet length */ -+ u16 TxPktLength; -+ /** Tx packet offset */ -+ u16 TxPktOffset; -+ /** Tx packet type */ -+ u16 TxPktType; -+ /** Tx Control */ -+ u32 TxControl; -+ /** reserved */ -+ u32 reserved[2]; -+} __ATTRIB_PACK__ TxPD, *PTxPD; -+ -+/** RxPD Descriptor */ -+typedef struct _RxPD -+{ -+ /** Bss Type */ -+ u8 BssType; -+ /** Bss Num */ -+ u8 BssNum; -+ /** Tx packet length */ -+ u16 RxPktLength; -+ /** Tx packet offset */ -+ u16 RxPktOffset; -+} __ATTRIB_PACK__ RxPD, *PRxPD; -+ -+#ifdef BIG_ENDIAN -+/** Convert from 16 bit little endian format to CPU format */ -+#define uap_le16_to_cpu(x) le16_to_cpu(x) -+/** Convert from 32 bit little endian format to CPU format */ -+#define uap_le32_to_cpu(x) le32_to_cpu(x) -+/** Convert from 64 bit little endian format to CPU format */ -+#define uap_le64_to_cpu(x) le64_to_cpu(x) -+/** Convert to 16 bit little endian format from CPU format */ -+#define uap_cpu_to_le16(x) cpu_to_le16(x) -+/** Convert to 32 bit little endian format from CPU format */ -+#define uap_cpu_to_le32(x) cpu_to_le32(x) -+/** Convert to 64 bit little endian format from CPU format */ -+#define uap_cpu_to_le64(x) cpu_to_le64(x) -+ -+/** Convert TxPD to little endian format from CPU format */ -+#define endian_convert_TxPD(x); \ -+ { \ -+ (x)->TxPktLength = uap_cpu_to_le16((x)->TxPktLength); \ -+ (x)->TxPktOffset = uap_cpu_to_le32((x)->TxPktOffset); \ -+ (x)->TxControl = uap_cpu_to_le32((x)->TxControl); \ -+ (x)->TxPktType = uap_cpu_to_le32((x)->TxPktType); \ -+ } -+ -+/** Convert RxPD from little endian format to CPU format */ -+#define endian_convert_RxPD(x); \ -+ { \ -+ (x)->RxPktLength = uap_le16_to_cpu((x)->RxPktLength); \ -+ (x)->RxPktOffset = uap_le32_to_cpu((x)->RxPktOffset); \ -+ } -+#else /* BIG_ENDIAN */ -+/** Do nothing */ -+#define uap_le16_to_cpu(x) x -+/** Do nothing */ -+#define uap_le32_to_cpu(x) x -+/** Do nothing */ -+#define uap_le64_to_cpu(x) x -+/** Do nothing */ -+#define uap_cpu_to_le16(x) x -+/** Do nothing */ -+#define uap_cpu_to_le32(x) x -+/** Do nothing */ -+#define uap_cpu_to_le64(x) x -+ -+/** Do nothing */ -+#define endian_convert_TxPD(x) -+/** Do nothing */ -+#define endian_convert_RxPD(x) -+#endif /* BIG_ENDIAN */ -+ -+/** Host Command ID : Function initialization */ -+#define HostCmd_CMD_FUNC_INIT 0x00a9 -+/** Host Command ID : Function shutdown */ -+#define HostCmd_CMD_FUNC_SHUTDOWN 0x00aa -+ -+/** Host Command id: SYS_INFO */ -+#define HOST_CMD_APCMD_SYS_INFO 0x00ae -+/** Host Command id: SYS_RESET */ -+#define HOST_CMD_APCMD_SYS_RESET 0x00af -+/** Host Command id: SYS_CONFIGURE */ -+#define HOST_CMD_APCMD_SYS_CONFIGURE 0x00b0 -+/** Host Command id: BSS_START */ -+#define HOST_CMD_APCMD_BSS_START 0x00b1 -+/** Host Command id: SYS_STOP */ -+#define HOST_CMD_APCMD_BSS_STOP 0x00b2 -+/** Host Command id: STA_LIST */ -+#define HOST_CMD_APCMD_STA_LIST 0x00b3 -+/** Host Command id: STA_FILTER_TABLE */ -+#define HOST_CMD_APCMD_STA_FILTER_TABLE 0x00b4 -+/** Host Command id: STA_DEAUTH */ -+#define HOST_CMD_APCMD_STA_DEAUTH 0x00b5 -+/** Host Command id: SOFT_RESET */ -+#define HOST_CMD_APCMD_SOFT_RESET 0x00d5 -+/** Host Command id: POWER_MGMT_EXT */ -+#define HOST_CMD_POWER_MGMT_EXT 0x00ef -+/** Host Command id: SLEEP_CONFIRM*/ -+#define HOST_CMD_SLEEP_CONFIRM 0x00d8 -+ -+/** TLV type : SSID */ -+#define TLV_TYPE_SSID 0x0000 -+/** TLV type : Rates */ -+#define TLV_TYPE_RATES 0x0001 -+/** TLV type : PHY DS */ -+#define TLV_TYPE_PHY_DS 0x0003 -+ -+/** TLV Id : Base id */ -+#define PROPRIETARY_TLV_BASE_ID 0x0100 -+/** TLV Id : AP_MAC_ADDRESS */ -+#define MRVL_AP_MAC_ADDRESS_TLV_ID (PROPRIETARY_TLV_BASE_ID + 43) -+/** TLV Id : Beacon period */ -+#define MRVL_BEACON_PERIOD_TLV_ID (PROPRIETARY_TLV_BASE_ID + 44) -+/** TLV Id : Dtim period */ -+#define MRVL_DTIM_PERIOD_TLV_ID (PROPRIETARY_TLV_BASE_ID + 45) -+/** TLV Id : Basic rates */ -+#define MRVL_BASIC_RATES_TLV_ID (PROPRIETARY_TLV_BASE_ID + 46) -+/** TLV Id : Tx Power */ -+#define MRVL_TX_POWER_TLV_ID (PROPRIETARY_TLV_BASE_ID + 47) -+/** TLV Id : Broadcast SSID control */ -+#define MRVL_BCAST_SSID_CTL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 48) -+/** TLV Id : Preamble control */ -+#define MRVL_PREAMBLE_CTL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 49) -+/** TLV Id : Antenna control */ -+#define MRVL_ANTENNA_CTL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 50) -+/** TLV Id : RTS threshold */ -+#define MRVL_RTS_THRESHOLD_TLV_ID (PROPRIETARY_TLV_BASE_ID + 51) -+/** TLV Id : Radio control */ -+#define MRVL_RADIO_CTL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 52) -+/** TLV Id : TX data rate */ -+#define MRVL_TX_DATA_RATE_TLV_ID (PROPRIETARY_TLV_BASE_ID + 53) -+/** TLV Id : Packet forward control */ -+#define MRVL_PKT_FWD_CTL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 54) -+/** TLV Id : STA info */ -+#define MRVL_STA_INFO_TLV_ID (PROPRIETARY_TLV_BASE_ID + 55) -+/** TLV Id : STA MAC address filter */ -+#define MRVL_STA_MAC_ADDR_FILTER_TLV_ID (PROPRIETARY_TLV_BASE_ID + 56) -+/** TLV Id : STA ageout timer */ -+#define MRVL_STA_AGEOUT_TIMER_TLV_ID (PROPRIETARY_TLV_BASE_ID + 57) -+/** TLV Id : Security config */ -+#define MRVL_SECURITY_CFG_TLV_ID (PROPRIETARY_TLV_BASE_ID + 58) -+/** TLV Id : WEP KEY */ -+#define MRVL_WEP_KEY_TLV_ID (PROPRIETARY_TLV_BASE_ID + 59) -+/** TLV Id : WPA Passphrase */ -+#define MRVL_WPA_PASSPHRASE_TLV_ID (PROPRIETARY_TLV_BASE_ID + 60) -+ -+/** Action get */ -+#define ACTION_GET 0 -+/** Action set */ -+#define ACTION_SET 1 -+/** Length of ethernet address */ -+#ifndef ETH_ALEN -+#define ETH_ALEN 6 -+#endif -+ -+/** HostCmd_DS_GEN */ -+typedef struct -+{ -+ /** Command */ -+ u16 Command; -+ /** Size */ -+ u16 Size; -+ /** Sequence number */ -+ u16 SeqNum; -+ /** Result */ -+ u16 Result; -+} __ATTRIB_PACK__ HostCmd_DS_GEN; -+ -+/** Size of HostCmd_DS_GEN */ -+#define S_DS_GEN sizeof(HostCmd_DS_GEN) -+ -+/** _HostCmd_HEADER*/ -+typedef struct -+{ -+ /** Command Header : Command */ -+ u16 Command; -+ /** Command Header : Size */ -+ u16 Size; -+} __ATTRIB_PACK__ HostCmd_HEADER; -+ -+/** HostCmd_SYS_CONFIG */ -+typedef struct _HostCmd_SYS_CONFIG -+{ -+ /** CMD Action GET/SET*/ -+ u16 Action; -+ /** Tlv buffer */ -+ u8 TlvBuffer[0]; -+} __ATTRIB_PACK__ HostCmd_SYS_CONFIG; -+ -+/** HostCmd_DS_POWER_MGMT_EXT */ -+typedef struct _HostCmd_DS_POWER_MGMT_EXT -+{ -+ /** CMD Action Get/Set*/ -+ u16 action; -+ /** power mode */ -+ u16 power_mode; -+} __ATTRIB_PACK__ HostCmd_DS_POWER_MGMT_EXT; -+ -+/** _HostCmd_DS_COMMAND*/ -+typedef struct _HostCmd_DS_COMMAND -+{ -+ -+ /** Command Header : Command */ -+ u16 Command; -+ /** Command Header : Size */ -+ u16 Size; -+ /** Command Header : Sequence number */ -+ u16 SeqNum; -+ /** Command Header : Result */ -+ u16 Result; -+ /** Command Body */ -+ union -+ { -+ HostCmd_SYS_CONFIG sys_config; -+ HostCmd_DS_POWER_MGMT_EXT pm_cfg; -+ -+ } params; -+} __ATTRIB_PACK__ HostCmd_DS_COMMAND; -+ -+/** MrvlIEtypesHeader_*/ -+typedef struct _MrvlIEtypesHeader -+{ -+ /** Header type */ -+ u16 Type; -+ /** Header length */ -+ u16 Len; -+} __ATTRIB_PACK__ MrvlIEtypesHeader_t; -+ -+/** MrvlIEtypes_Data_t */ -+typedef struct _MrvlIEtypes_Data_t -+{ -+ /** Header */ -+ MrvlIEtypesHeader_t Header; -+ /** Data */ -+ u8 Data[1]; -+} __ATTRIB_PACK__ MrvlIEtypes_Data_t; -+ -+/** MrvlIEtypes_ChanListParamSet_t */ -+typedef struct _MrvlIEtypes_MacAddr_t -+{ -+ /** Header */ -+ MrvlIEtypesHeader_t Header; -+ /** AP MAC address */ -+ u8 ApMacAddr[ETH_ALEN]; -+} __ATTRIB_PACK__ MrvlIEtypes_MacAddr_t; -+ -+/** Event ID: BSS started */ -+#define MICRO_AP_EV_ID_BSS_START 46 -+ -+/** Event ID: BSS idle event */ -+#define MICRO_AP_EV_BSS_IDLE 67 -+ -+/** Event ID: BSS active event */ -+#define MICRO_AP_EV_BSS_ACTIVE 68 -+ -+/** Event ID: PS_AWAKE */ -+#define EVENT_PS_AWAKE 0x0a -+ -+/** Event ID: PS_SLEEP */ -+#define EVENT_PS_SLEEP 0x0b -+ -+/** PS_STATE */ -+typedef enum _PS_STATE -+{ -+ PS_STATE_AWAKE, -+ PS_STATE_PRE_SLEEP, -+ PS_STATE_SLEEP -+} PS_STATE; -+ -+/** TLV type: AP Sleep param */ -+#define TLV_TYPE_AP_SLEEP_PARAM (PROPRIETARY_TLV_BASE_ID + 106) -+/** TLV type: AP Inactivity Sleep param */ -+#define TLV_TYPE_AP_INACT_SLEEP_PARAM (PROPRIETARY_TLV_BASE_ID + 107) -+ -+/** MrvlIEtypes_sleep_param_t */ -+typedef struct _MrvlIEtypes_sleep_param_t -+{ -+ /** Header */ -+ MrvlIEtypesHeader_t header; -+ /** control bitmap */ -+ u32 ctrl_bitmap; -+ /** min_sleep */ -+ u32 min_sleep; -+ /** max_sleep */ -+ u32 max_sleep; -+} __ATTRIB_PACK__ MrvlIEtypes_sleep_param_t; -+ -+/** MrvlIEtypes_inact_sleep_param_t */ -+typedef struct _MrvlIEtypes_inact_sleep_param_t -+{ -+ /** Header */ -+ MrvlIEtypesHeader_t header; -+ /** inactivity timeout */ -+ u32 inactivity_to; -+ /** min_awake */ -+ u32 min_awake; -+ /** max_awake */ -+ u32 max_awake; -+} __ATTRIB_PACK__ MrvlIEtypes_inact_sleep_param_t; -+ -+/** AP_Event */ -+typedef struct _AP_Event -+{ -+ /** Event ID */ -+ u32 EventId; -+ /* -+ * Reserved for STA_ASSOCIATED event and contains -+ * status information for the MIC_COUNTERMEASURES event. -+ */ -+ /** Reserved/status */ -+ u16 status; -+ /** AP MAC address */ -+ u8 MacAddr[ETH_ALEN]; -+} __ATTRIB_PACK__ AP_Event; -+#endif /* _UAP_FW_H */ -diff -Naupr linux-2.6.37/drivers/net/wireless/libertas_uap/uap_headers.h linux-2.6.37-new/drivers/net/wireless/libertas_uap/uap_headers.h ---- linux-2.6.37/drivers/net/wireless/libertas_uap/uap_headers.h 1969-12-31 17:00:00.000000000 -0700 -+++ linux-2.6.37-new/drivers/net/wireless/libertas_uap/uap_headers.h 2011-01-08 06:01:04.043835537 -0700 -@@ -0,0 +1,64 @@ -+/** @file uap_headers.h -+ * -+ * @brief This file contains all the necessary include file. -+ * -+ * Copyright (C) 2008-2009, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available along with the File in the gpl.txt file or by writing to -+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ * -+ */ -+#ifndef _UAP_HEADERS_H -+#define _UAP_HEADERS_H -+ -+/* Linux header files */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) -+#include -+#else -+#include -+#endif -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) -+#include -+#endif -+ -+/* Net header files */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "uap_drv.h" -+#include "uap_fw.h" -+ -+#include -+#include -+#include -+#include -+#include "uap_sdio_mmc.h" -+ -+#endif /* _UAP_HEADERS_H */ -diff -Naupr linux-2.6.37/drivers/net/wireless/libertas_uap/uap_main.c linux-2.6.37-new/drivers/net/wireless/libertas_uap/uap_main.c ---- linux-2.6.37/drivers/net/wireless/libertas_uap/uap_main.c 1969-12-31 17:00:00.000000000 -0700 -+++ linux-2.6.37-new/drivers/net/wireless/libertas_uap/uap_main.c 2011-01-08 06:01:04.048835193 -0700 -@@ -0,0 +1,1830 @@ -+/** @file uap_main.c -+ * @brief This file contains the major functions in uAP -+ * driver. It includes init, exit etc.. -+ * This file also contains the initialization for SW, -+ * FW and HW -+ * -+ * Copyright (C) 2008-2009, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available along with the File in the gpl.txt file or by writing to -+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ * -+ */ -+/** -+ * @mainpage uAP Linux Driver -+ * -+ * @section overview_sec Overview -+ * -+ * This is Linux reference driver for Marvell uAP. -+ * -+ * @section copyright_sec Copyright -+ * -+ * Copyright (C) 2008, Marvell International Ltd. -+ * -+ */ -+ -+#include "uap_headers.h" -+ -+/** -+ * the global variable of a pointer to uap_private -+ * structure variable -+ */ -+uap_private *uappriv = NULL; -+#ifdef DEBUG_LEVEL1 -+#define DEFAULT_DEBUG_MASK (DBG_MSG | DBG_FATAL | DBG_ERROR) -+u32 drvdbg = DEFAULT_DEBUG_MASK; -+#endif -+/** Helper name */ -+char *helper_name = NULL; -+/** Firmware name */ -+char *fw_name = NULL; -+ -+/** Semaphore for add/remove card */ -+SEMAPHORE AddRemoveCardSem; -+ -+/******************************************************** -+ Local Functions -+********************************************************/ -+/** -+ * @brief This function send sleep confirm command to firmware -+ * -+ * @param priv A pointer to uap_private structure -+ * @return UAP_STATUS_SUCCESS for success otherwise UAP_STATUS_FAILURE -+ */ -+static int -+uap_dnld_sleep_confirm_cmd(uap_private * priv) -+{ -+ uap_adapter *Adapter = priv->adapter; -+ int ret = UAP_STATUS_SUCCESS; -+ ENTER(); -+ PRINTM(CMND, "Sleep confirm\n"); -+ Adapter->cmd_pending = TRUE; -+ Adapter->cmd_wait_option = HostCmd_OPTION_WAITFORRSP_SLEEPCONFIRM; -+ ret = -+ sbi_host_to_card(priv, (u8 *) & Adapter->PSConfirmSleep, -+ sizeof(PS_CMD_ConfirmSleep)); -+ if (ret != UAP_STATUS_SUCCESS) { -+ Adapter->ps_state = PS_STATE_AWAKE; -+ Adapter->cmd_pending = FALSE; -+ Adapter->cmd_wait_option = FALSE; -+ } -+ LEAVE(); -+ return ret; -+} -+ -+/** -+ * @brief This function process sleep confirm resp from firmware -+ * -+ * @param priv A pointer to uap_private structure -+ * @param resp A pointer to resp buf -+ * @param resp_len resp buf len -+ * @return UAP_STATUS_SUCCESS for success otherwise UAP_STATUS_FAILURE -+ */ -+int -+uap_process_sleep_confirm_resp(uap_private * priv, u8 * resp, int resp_len) -+{ -+ int ret = UAP_STATUS_SUCCESS; -+ HostCmd_DS_COMMAND *cmd; -+ uap_adapter *Adapter = priv->adapter; -+ ENTER(); -+ PRINTM(CMND, "Sleep confirm resp\n"); -+ if (!resp_len) { -+ PRINTM(ERROR, "Cmd Size is 0\n"); -+ ret = -EFAULT; -+ goto done; -+ } -+ cmd = (HostCmd_DS_COMMAND *) resp; -+ cmd->Result = uap_le16_to_cpu(cmd->Result); -+ if (cmd->Result != UAP_STATUS_SUCCESS) { -+ PRINTM(ERROR, "HOST_CMD_APCMD_PS_SLEEP_CONFIRM fail=%x\n", cmd->Result); -+ ret = -EFAULT; -+ } -+ done: -+ if (ret == UAP_STATUS_SUCCESS) -+ Adapter->ps_state = PS_STATE_SLEEP; -+ else -+ Adapter->ps_state = PS_STATE_AWAKE; -+ LEAVE(); -+ return ret; -+} -+ -+/** -+ * @brief This function checks condition and prepares to -+ * send sleep confirm command to firmware if OK. -+ * -+ * @param priv A pointer to uap_private structure -+ * @return n/a -+ */ -+static void -+uap_ps_cond_check(uap_private * priv) -+{ -+ uap_adapter *Adapter = priv->adapter; -+ -+ ENTER(); -+ if (!priv->uap_dev.cmd_sent && -+ !Adapter->cmd_pending && !Adapter->IntCounter) { -+ uap_dnld_sleep_confirm_cmd(priv); -+ } else { -+ PRINTM(INFO, "Delay Sleep Confirm (%s%s%s)\n", -+ (priv->uap_dev.cmd_sent) ? "D" : "", -+ (Adapter->cmd_pending) ? "C" : "", -+ (Adapter->IntCounter) ? "I" : ""); -+ } -+ LEAVE(); -+} -+ -+/** -+ * @brief This function add cmd to cmdQ and waiting for response -+ * -+ * @param priv A pointer to uap_private structure -+ * @param skb A pointer to the skb for process -+ * @param wait_option Wait option -+ * @return UAP_STATUS_SUCCESS for success otherwise UAP_STATUS_FAILURE -+ */ -+static int -+uap_process_cmd(uap_private * priv, struct sk_buff *skb, u8 wait_option) -+{ -+ uap_adapter *Adapter = priv->adapter; -+ int ret = UAP_STATUS_SUCCESS; -+ HostCmd_DS_COMMAND *cmd; -+ u8 *headptr; -+ ENTER(); -+ if (Adapter->HardwareStatus != HWReady) { -+ PRINTM(ERROR, "Hw not ready, uap_process_cmd\n"); -+ kfree(skb); -+ LEAVE(); -+ return -EFAULT; -+ } -+ skb->cb[0] = wait_option; -+ headptr = skb->data; -+ *(u16 *) & headptr[0] = uap_cpu_to_le16(skb->len); -+ *(u16 *) & headptr[2] = uap_cpu_to_le16(MV_TYPE_CMD); -+ cmd = (HostCmd_DS_COMMAND *) (skb->data + INTF_HEADER_LEN); -+ Adapter->SeqNum++; -+ cmd->SeqNum = uap_cpu_to_le16(Adapter->SeqNum); -+ PRINTM(CMND, "process_cmd: %x\n", cmd->Command); -+ DBG_HEXDUMP(CMD_D, "process_cmd", (u8 *) cmd, cmd->Size); -+ if (!wait_option) { -+ skb_queue_tail(&priv->adapter->cmd_queue, skb); -+ wake_up_interruptible(&priv->MainThread.waitQ); -+ LEAVE(); -+ return ret; -+ } -+ if (OS_ACQ_SEMAPHORE_BLOCK(&Adapter->CmdSem)) { -+ PRINTM(ERROR, "Acquire semaphore error, uap_prepare_cmd\n"); -+ kfree(skb); -+ LEAVE(); -+ return -EBUSY; -+ } -+ skb_queue_tail(&priv->adapter->cmd_queue, skb); -+ Adapter->CmdWaitQWoken = FALSE; -+ wake_up_interruptible(&priv->MainThread.waitQ); -+ /* Sleep until response is generated by FW */ -+ if (wait_option == HostCmd_OPTION_WAITFORRSP_TIMEOUT) { -+ if (!os_wait_interruptible_timeout -+ (Adapter->cmdwait_q, Adapter->CmdWaitQWoken, MRVDRV_TIMER_20S)) { -+ PRINTM(ERROR, "Cmd timeout\n"); -+ Adapter->cmd_pending = FALSE; -+ ret = -EFAULT; -+ } -+ } else -+ wait_event_interruptible(Adapter->cmdwait_q, Adapter->CmdWaitQWoken); -+ OS_REL_SEMAPHORE(&Adapter->CmdSem); -+ LEAVE(); -+ return ret; -+} -+ -+/** -+ * @brief Inspect the response buffer for pointers to expected TLVs -+ * -+ * -+ * @param pTlv Pointer to the start of the TLV buffer to parse -+ * @param tlvBufSize Size of the TLV buffer -+ * @param reqTlvType request tlv's tlvtype -+ * @param ppTlv Output parameter: Pointer to the request TLV if found -+ * -+ * @return void -+ */ -+static void -+uap_get_tlv_ptrs(MrvlIEtypes_Data_t * pTlv, int tlvBufSize, -+ u16 reqTlvType, MrvlIEtypes_Data_t ** ppTlv) -+{ -+ MrvlIEtypes_Data_t *pCurrentTlv; -+ int tlvBufLeft; -+ u16 tlvType; -+ u16 tlvLen; -+ -+ ENTER(); -+ pCurrentTlv = pTlv; -+ tlvBufLeft = tlvBufSize; -+ *ppTlv = NULL; -+ PRINTM(INFO, "uap_get_tlv: tlvBufSize = %d, reqTlvType=%x\n", tlvBufSize, -+ reqTlvType); -+ while (tlvBufLeft >= sizeof(MrvlIEtypesHeader_t)) { -+ tlvType = uap_le16_to_cpu(pCurrentTlv->Header.Type); -+ tlvLen = uap_le16_to_cpu(pCurrentTlv->Header.Len); -+ if (reqTlvType == tlvType) -+ *ppTlv = (MrvlIEtypes_Data_t *) pCurrentTlv; -+ if (*ppTlv) { -+ HEXDUMP("TLV Buf", (u8 *) * ppTlv, tlvLen); -+ break; -+ } -+ tlvBufLeft -= (sizeof(pTlv->Header) + tlvLen); -+ pCurrentTlv = (MrvlIEtypes_Data_t *) (pCurrentTlv->Data + tlvLen); -+ } /* while */ -+ LEAVE(); -+} -+ -+/** -+ * @brief This function get mac -+ * -+ * @param priv A pointer to uap_private structure -+ * @return UAP_STATUS_SUCCESS on success, otherwise failure code -+ */ -+static int -+uap_get_mac_address(uap_private * priv) -+{ -+ int ret = UAP_STATUS_SUCCESS; -+ u32 CmdSize; -+ HostCmd_DS_COMMAND *cmd; -+ uap_adapter *Adapter = priv->adapter; -+ struct sk_buff *skb; -+ MrvlIEtypes_MacAddr_t *pMacAddrTlv; -+ MrvlIEtypes_Data_t *pTlv; -+ u16 tlvBufSize; -+ ENTER(); -+ skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER); -+ if (!skb) { -+ PRINTM(ERROR, "No free skb\n"); -+ ret = -ENOMEM; -+ goto done; -+ } -+ CmdSize = -+ S_DS_GEN + sizeof(HostCmd_SYS_CONFIG) + sizeof(MrvlIEtypes_MacAddr_t); -+ cmd = (HostCmd_DS_COMMAND *) (skb->data + INTF_HEADER_LEN); -+ cmd->Command = uap_cpu_to_le16(HOST_CMD_APCMD_SYS_CONFIGURE); -+ cmd->Size = uap_cpu_to_le16(CmdSize); -+ cmd->params.sys_config.Action = uap_cpu_to_le16(ACTION_GET); -+ pMacAddrTlv = -+ (MrvlIEtypes_MacAddr_t *) (skb->data + INTF_HEADER_LEN + S_DS_GEN + -+ sizeof(HostCmd_SYS_CONFIG)); -+ pMacAddrTlv->Header.Type = uap_cpu_to_le16(MRVL_AP_MAC_ADDRESS_TLV_ID); -+ pMacAddrTlv->Header.Len = uap_cpu_to_le16(ETH_ALEN); -+ skb_put(skb, CmdSize + INTF_HEADER_LEN); -+ if (UAP_STATUS_SUCCESS != -+ uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP_TIMEOUT)) { -+ PRINTM(ERROR, "Fail to process cmd SYS_CONFIGURE Query\n"); -+ ret = -EFAULT; -+ goto done; -+ } -+ if (!Adapter->CmdSize) { -+ PRINTM(ERROR, "Cmd Size is 0\n"); -+ ret = -EFAULT; -+ goto done; -+ } -+ cmd = (HostCmd_DS_COMMAND *) Adapter->CmdBuf; -+ cmd->Result = uap_le16_to_cpu(cmd->Result); -+ if (cmd->Result != UAP_STATUS_SUCCESS) { -+ PRINTM(ERROR, "uap_get_mac_address fail=%x\n", cmd->Result); -+ ret = -EFAULT; -+ goto done; -+ } -+ pTlv = -+ (MrvlIEtypes_Data_t *) (Adapter->CmdBuf + S_DS_GEN + -+ sizeof(HostCmd_SYS_CONFIG)); -+ tlvBufSize = Adapter->CmdSize - S_DS_GEN - sizeof(HostCmd_SYS_CONFIG); -+ uap_get_tlv_ptrs(pTlv, tlvBufSize, MRVL_AP_MAC_ADDRESS_TLV_ID, -+ (MrvlIEtypes_Data_t **) & pMacAddrTlv); -+ if (pMacAddrTlv) { -+ memcpy(priv->uap_dev.netdev->dev_addr, pMacAddrTlv->ApMacAddr, -+ ETH_ALEN); -+ HEXDUMP("Original MAC addr", priv->uap_dev.netdev->dev_addr, ETH_ALEN); -+ } -+ done: -+ LEAVE(); -+ return ret; -+} -+ -+/** -+ * @brief This function checks the conditions and sends packet to device -+ * -+ * @param priv A pointer to uap_private structure -+ * @param skb A pointer to the skb for process -+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE -+ */ -+static int -+uap_process_tx(uap_private * priv, struct sk_buff *skb) -+{ -+ uap_adapter *Adapter = priv->adapter; -+ int ret = UAP_STATUS_SUCCESS; -+ TxPD *pLocalTxPD; -+ u8 *headptr; -+ struct sk_buff *newskb; -+ int newheadlen; -+ ENTER(); -+ ASSERT(skb); -+ if (!skb) { -+ LEAVE(); -+ return UAP_STATUS_FAILURE; -+ } -+ if (skb_headroom(skb) < (sizeof(TxPD) + INTF_HEADER_LEN + HEADER_ALIGNMENT)) { -+ newheadlen = sizeof(TxPD) + INTF_HEADER_LEN + HEADER_ALIGNMENT; -+ PRINTM(WARN, "Tx: Insufficient skb headroom %d\n", skb_headroom(skb)); -+ /* Insufficient skb headroom - allocate a new skb */ -+ newskb = skb_realloc_headroom(skb, newheadlen); -+ if (unlikely(newskb == NULL)) { -+ PRINTM(ERROR, "Tx: Cannot allocate skb\n"); -+ ret = UAP_STATUS_FAILURE; -+ goto done; -+ } -+ kfree_skb(skb); -+ skb = newskb; -+ PRINTM(INFO, "new skb headroom %d\n", skb_headroom(skb)); -+ } -+ /* headptr should be aligned */ -+ headptr = skb->data - sizeof(TxPD) - INTF_HEADER_LEN; -+ headptr = (u8 *) ((u32) headptr & ~((u32) (HEADER_ALIGNMENT - 1))); -+ -+ pLocalTxPD = (TxPD *) (headptr + INTF_HEADER_LEN); -+ memset(pLocalTxPD, 0, sizeof(TxPD)); -+ pLocalTxPD->BssType = PKT_TYPE_MICROAP; -+ pLocalTxPD->TxPktLength = skb->len; -+ /* offset of actual data */ -+ pLocalTxPD->TxPktOffset = (long) skb->data - (long) pLocalTxPD; -+ endian_convert_TxPD(pLocalTxPD); -+ *(u16 *) & headptr[0] = -+ uap_cpu_to_le16(skb->len + ((long) skb->data - (long) headptr)); -+ *(u16 *) & headptr[2] = uap_cpu_to_le16(MV_TYPE_DAT); -+ ret = -+ sbi_host_to_card(priv, headptr, -+ skb->len + ((long) skb->data - (long) headptr)); -+ if (ret) { -+ PRINTM(ERROR, "uap_process_tx Error: sbi_host_to_card failed: 0x%X\n", -+ ret); -+ Adapter->dbg.num_tx_host_to_card_failure++; -+ goto done; -+ } -+ PRINTM(DATA, "Data => FW\n"); -+ DBG_HEXDUMP(DAT_D, "Tx", headptr, -+ MIN(skb->len + sizeof(TxPD), DATA_DUMP_LEN)); -+ done: -+ /* Freed skb */ -+ kfree_skb(skb); -+ LEAVE(); -+ return ret; -+} -+ -+/** -+ * @brief This function initializes the adapter structure -+ * and set default value to the member of adapter. -+ * -+ * @param priv A pointer to uap_private structure -+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE -+ */ -+static int -+uap_init_sw(uap_private * priv) -+{ -+ uap_adapter *Adapter = priv->adapter; -+ -+ ENTER(); -+ -+ if (!(Adapter->CmdBuf = kmalloc(MRVDRV_SIZE_OF_CMD_BUFFER, GFP_KERNEL))) { -+ PRINTM(INFO, "Failed to allocate command buffer!\n"); -+ LEAVE(); -+ return UAP_STATUS_FAILURE; -+ } -+ -+ Adapter->cmd_pending = FALSE; -+ Adapter->CmdWaitQWoken = FALSE; -+ Adapter->ps_state = PS_STATE_AWAKE; -+ Adapter->WakeupTries = 0; -+ -+ memset(&Adapter->PSConfirmSleep, 0, sizeof(PS_CMD_ConfirmSleep)); -+ /** SDIO header */ -+ Adapter->PSConfirmSleep.SDLen = -+ uap_cpu_to_le16(sizeof(PS_CMD_ConfirmSleep)); -+ Adapter->PSConfirmSleep.SDType = uap_cpu_to_le16(MV_TYPE_CMD); -+ Adapter->PSConfirmSleep.SeqNum = 0; -+ Adapter->PSConfirmSleep.Command = uap_cpu_to_le16(HOST_CMD_SLEEP_CONFIRM); -+ Adapter->PSConfirmSleep.Size = uap_cpu_to_le16(sizeof(HostCmd_DS_GEN)); -+ Adapter->PSConfirmSleep.Result = 0; -+ -+ init_waitqueue_head(&Adapter->cmdwait_q); -+ OS_INIT_SEMAPHORE(&Adapter->CmdSem); -+ -+ skb_queue_head_init(&Adapter->tx_queue); -+ skb_queue_head_init(&Adapter->cmd_queue); -+ -+ /* Status variable */ -+ Adapter->HardwareStatus = HWInitializing; -+ -+ /* PnP support */ -+ Adapter->SurpriseRemoved = FALSE; -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) -+ Adapter->nl_sk = netlink_kernel_create(NETLINK_MARVELL, -+ NL_MULTICAST_GROUP, NULL, -+ THIS_MODULE); -+#else -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) -+ Adapter->nl_sk = netlink_kernel_create(NETLINK_MARVELL, -+ NL_MULTICAST_GROUP, NULL, NULL, -+ THIS_MODULE); -+#else -+ Adapter->nl_sk = netlink_kernel_create(&init_net, NETLINK_MARVELL, -+ NL_MULTICAST_GROUP, NULL, NULL, -+ THIS_MODULE); -+#endif -+#endif -+ if (!Adapter->nl_sk) { -+ PRINTM(ERROR, -+ "Could not initialize netlink event passing mechanism!\n"); -+ } -+ LEAVE(); -+ return UAP_STATUS_SUCCESS; -+} -+ -+/** -+ * @brief This function sends FUNC_INIT command to firmware -+ * -+ * @param priv A pointer to uap_private structure -+ * @return UAP_STATUS_SUCCESS on success, otherwise failure code -+ */ -+static int -+uap_func_init(uap_private * priv) -+{ -+ int ret = UAP_STATUS_SUCCESS; -+ u32 CmdSize; -+ HostCmd_DS_GEN *cmd; -+ uap_adapter *Adapter = priv->adapter; -+ struct sk_buff *skb; -+ ENTER(); -+ if (Adapter->HardwareStatus != HWReady) { -+ PRINTM(ERROR, "uap_func_init:Hardware is not ready!\n"); -+ ret = -EFAULT; -+ goto done; -+ } -+ skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER); -+ if (!skb) { -+ PRINTM(ERROR, "No free skb\n"); -+ ret = -ENOMEM; -+ goto done; -+ } -+ CmdSize = sizeof(HostCmd_DS_GEN); -+ cmd = (HostCmd_DS_GEN *) (skb->data + INTF_HEADER_LEN); -+ cmd->Command = uap_cpu_to_le16(HostCmd_CMD_FUNC_INIT); -+ cmd->Size = uap_cpu_to_le16(CmdSize); -+ skb_put(skb, CmdSize + INTF_HEADER_LEN); -+ PRINTM(CMND, "HostCmd_CMD_FUNC_INIT\n"); -+ if (UAP_STATUS_SUCCESS != -+ uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP_TIMEOUT)) { -+ PRINTM(ERROR, "Fail to process cmd HostCmd_CMD_FUNC_INIT\n"); -+ ret = -EFAULT; -+ goto done; -+ } -+ done: -+ LEAVE(); -+ return ret; -+} -+ -+/** -+ * @brief This function sends FUNC_SHUTDOWN command to firmware -+ * -+ * @param priv A pointer to uap_private structure -+ * @return UAP_STATUS_SUCCESS on success, otherwise failure code -+ */ -+static int __exit -+uap_func_shutdown(uap_private * priv) -+{ -+ int ret = UAP_STATUS_SUCCESS; -+ u32 CmdSize; -+ HostCmd_DS_GEN *cmd; -+ uap_adapter *Adapter = priv->adapter; -+ struct sk_buff *skb; -+ ENTER(); -+ if (Adapter->HardwareStatus != HWReady) { -+ PRINTM(ERROR, "uap_func_shutdown:Hardware is not ready!\n"); -+ ret = -EFAULT; -+ goto done; -+ } -+ skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER); -+ if (!skb) { -+ PRINTM(ERROR, "No free skb\n"); -+ ret = -ENOMEM; -+ goto done; -+ } -+ CmdSize = sizeof(HostCmd_DS_GEN); -+ cmd = (HostCmd_DS_GEN *) (skb->data + INTF_HEADER_LEN); -+ cmd->Command = uap_cpu_to_le16(HostCmd_CMD_FUNC_SHUTDOWN); -+ cmd->Size = uap_cpu_to_le16(CmdSize); -+ skb_put(skb, CmdSize + INTF_HEADER_LEN); -+ PRINTM(CMND, "HostCmd_CMD_FUNC_SHUTDOWN\n"); -+ if (UAP_STATUS_SUCCESS != -+ uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP_TIMEOUT)) { -+ PRINTM(ERROR, "Fail to process cmd HostCmd_CMD_FUNC_SHUTDOWN\n"); -+ ret = -EFAULT; -+ goto done; -+ } -+ done: -+ LEAVE(); -+ return ret; -+} -+ -+/** -+ * @brief This function initializes firmware -+ * -+ * @param priv A pointer to uap_private structure -+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE -+ */ -+static int -+uap_init_fw(uap_private * priv) -+{ -+ int ret = UAP_STATUS_SUCCESS; -+ ENTER(); -+ sbi_disable_host_int(priv); -+ /* Check if firmware is already running */ -+ if (sbi_check_fw_status(priv, 1) == UAP_STATUS_SUCCESS) { -+ PRINTM(MSG, "UAP FW already running! Skip FW download\n"); -+ } else { -+ if ((ret = request_firmware(&priv->fw_helper, helper_name, -+ priv->hotplug_device)) < 0) { -+ PRINTM(FATAL, -+ "request_firmware() failed (helper), error code = %#x\n", -+ ret); -+ goto done; -+ } -+ -+ /* Download the helper */ -+ ret = sbi_prog_helper(priv); -+ -+ if (ret) { -+ PRINTM(FATAL, -+ "Bootloader in invalid state! Helper download failed!\n"); -+ ret = UAP_STATUS_FAILURE; -+ goto done; -+ } -+ if ((ret = request_firmware(&priv->firmware, fw_name, -+ priv->hotplug_device)) < 0) { -+ PRINTM(FATAL, "request_firmware() failed, error code = %#x\n", ret); -+ goto done; -+ } -+ -+ /* Download the main firmware via the helper firmware */ -+ if (sbi_prog_fw_w_helper(priv)) { -+ PRINTM(FATAL, "UAP FW download failed!\n"); -+ ret = UAP_STATUS_FAILURE; -+ goto done; -+ } -+ /* Check if the firmware is downloaded successfully or not */ -+ if (sbi_check_fw_status(priv, MAX_FIRMWARE_POLL_TRIES) == -+ UAP_STATUS_FAILURE) { -+ PRINTM(FATAL, "FW failed to be active in time!\n"); -+ ret = UAP_STATUS_FAILURE; -+ goto done; -+ } -+ PRINTM(MSG, "UAP FW is active\n"); -+ } -+ sbi_enable_host_int(priv); -+ priv->adapter->HardwareStatus = HWReady; -+ if (uap_func_init(priv) != UAP_STATUS_SUCCESS) { -+ ret = UAP_STATUS_FAILURE; -+ goto done; -+ } -+ done: -+ if (priv->fw_helper) -+ release_firmware(priv->fw_helper); -+ if (priv->firmware) -+ release_firmware(priv->firmware); -+ LEAVE(); -+ return ret; -+ -+} -+ -+/** -+ * @brief This function frees the structure of adapter -+ * -+ * @param priv A pointer to uap_private structure -+ * @return n/a -+ */ -+static void -+uap_free_adapter(uap_private * priv) -+{ -+ uap_adapter *Adapter = priv->adapter; -+ -+ ENTER(); -+ -+ if (Adapter) { -+ if ((Adapter->nl_sk) && ((Adapter->nl_sk)->sk_socket)) { -+ sock_release((Adapter->nl_sk)->sk_socket); -+ Adapter->nl_sk = NULL; -+ } -+ if (Adapter->CmdBuf) -+ kfree(Adapter->CmdBuf); -+ skb_queue_purge(&priv->adapter->tx_queue); -+ skb_queue_purge(&priv->adapter->cmd_queue); -+ /* Free the adapter object itself */ -+ kfree(Adapter); -+ priv->adapter = NULL; -+ } -+ -+ LEAVE(); -+} -+ -+/** -+ * @brief This function handles the major job in uap driver. -+ * it handles the event generated by firmware, rx data received -+ * from firmware and tx data sent from kernel. -+ * -+ * @param data A pointer to uap_thread structure -+ * @return BT_STATUS_SUCCESS -+ */ -+static int -+uap_service_main_thread(void *data) -+{ -+ uap_thread *thread = data; -+ uap_private *priv = thread->priv; -+ uap_adapter *Adapter = priv->adapter; -+ wait_queue_t wait; -+ u8 ireg = 0; -+ struct sk_buff *skb; -+ ENTER(); -+ uap_activate_thread(thread); -+ init_waitqueue_entry(&wait, current); -+ current->flags |= PF_NOFREEZE; -+ -+ for (;;) { -+ add_wait_queue(&thread->waitQ, &wait); -+ OS_SET_THREAD_STATE(TASK_INTERRUPTIBLE); -+ if ((Adapter->WakeupTries) || -+ (!Adapter->IntCounter && Adapter->ps_state == PS_STATE_PRE_SLEEP) || -+ (!priv->adapter->IntCounter -+ && (priv->uap_dev.data_sent || -+ skb_queue_empty(&priv->adapter->tx_queue)) -+ && (priv->uap_dev.cmd_sent || Adapter->cmd_pending || -+ skb_queue_empty(&priv->adapter->cmd_queue)) -+ )) { -+ PRINTM(INFO, "Main: Thread sleeping...\n"); -+ schedule(); -+ } -+ OS_SET_THREAD_STATE(TASK_RUNNING); -+ remove_wait_queue(&thread->waitQ, &wait); -+ if (kthread_should_stop() || Adapter->SurpriseRemoved) { -+ PRINTM(INFO, "main-thread: break from main thread: " -+ "SurpriseRemoved=0x%x\n", Adapter->SurpriseRemoved); -+ /* Cancel pending command */ -+ if (Adapter->cmd_pending == TRUE) { -+ /* Wake up cmd Q */ -+ Adapter->CmdWaitQWoken = TRUE; -+ wake_up_interruptible(&Adapter->cmdwait_q); -+ } -+ break; -+ } -+ -+ PRINTM(INFO, "Main: Thread waking up...\n"); -+ if (priv->adapter->IntCounter) { -+ OS_INT_DISABLE; -+ Adapter->IntCounter = 0; -+ OS_INT_RESTORE; -+ sbi_get_int_status(priv, &ireg); -+ } else if ((priv->adapter->ps_state == PS_STATE_SLEEP) && -+ (!skb_queue_empty(&priv->adapter->cmd_queue) || -+ !skb_queue_empty(&priv->adapter->tx_queue))) { -+ priv->adapter->WakeupTries++; -+ PRINTM(CMND, "%lu : Wakeup device...\n", os_time_get()); -+ sbi_wakeup_firmware(priv); -+ continue; -+ } -+ if (Adapter->ps_state == PS_STATE_PRE_SLEEP) -+ uap_ps_cond_check(priv); -+ -+ /* The PS state is changed during processing of Sleep Request event -+ above */ -+ if ((Adapter->ps_state == PS_STATE_SLEEP) || -+ (Adapter->ps_state == PS_STATE_PRE_SLEEP)) -+ continue; -+ /* Execute the next command */ -+ if (!priv->uap_dev.cmd_sent && !Adapter->cmd_pending && -+ (Adapter->HardwareStatus == HWReady)) { -+ if (!skb_queue_empty(&priv->adapter->cmd_queue)) { -+ skb = skb_dequeue(&priv->adapter->cmd_queue); -+ if (skb) { -+ Adapter->CmdSize = 0; -+ Adapter->cmd_pending = TRUE; -+ Adapter->cmd_wait_option = skb->cb[0]; -+ if (sbi_host_to_card(priv, skb->data, skb->len)) { -+ PRINTM(ERROR, "Cmd:sbi_host_to_card failed!\n"); -+ Adapter->cmd_pending = FALSE; -+ Adapter->dbg.num_cmd_host_to_card_failure++; -+ /* Wake up cmd Q */ -+ Adapter->CmdWaitQWoken = TRUE; -+ wake_up_interruptible(&Adapter->cmdwait_q); -+ } else { -+ if (Adapter->cmd_wait_option == -+ HostCmd_OPTION_WAITFORSEND) { -+ /* Wake up cmd Q */ -+ Adapter->CmdWaitQWoken = TRUE; -+ wake_up_interruptible(&Adapter->cmdwait_q); -+ Adapter->cmd_wait_option = FALSE; -+ } -+ } -+ kfree_skb(skb); -+ } -+ } -+ } -+ if (!priv->uap_dev.data_sent && (Adapter->HardwareStatus == HWReady)) { -+ if (!skb_queue_empty(&priv->adapter->tx_queue)) { -+ skb = skb_dequeue(&priv->adapter->tx_queue); -+ if (skb) { -+ if (uap_process_tx(priv, skb)) { -+ priv->stats.tx_dropped++; -+ priv->stats.tx_errors++; -+ os_start_queue(priv); -+ } else { -+ priv->stats.tx_packets++; -+ priv->stats.tx_bytes += skb->len; -+ } -+ -+ } -+ } -+ } -+ } -+ uap_deactivate_thread(thread); -+ LEAVE(); -+ return UAP_STATUS_SUCCESS; -+} -+ -+/** -+ * @brief uap hostcmd ioctl handler -+ * -+ * @param dev A pointer to net_device structure -+ * @param req A pointer to ifreq structure -+ * @return UAP_STATUS_SUCCESS --success, otherwise fail -+ */ -+/********* format of ifr_data *************/ -+/* buf_len + Hostcmd_body */ -+/* buf_len: 4 bytes */ -+/* the length of the buf which */ -+/* can be used to return data */ -+/* to application */ -+/* Hostcmd_body */ -+/*******************************************/ -+static int -+uap_hostcmd_ioctl(struct net_device *dev, struct ifreq *req) -+{ -+ u32 buf_len; -+ HostCmd_HEADER head; -+ uap_private *priv = (uap_private *) netdev_priv(dev); -+ uap_adapter *Adapter = priv->adapter; -+ int ret = UAP_STATUS_SUCCESS; -+ struct sk_buff *skb; -+ -+ ENTER(); -+ -+ /* Sanity check */ -+ if (req->ifr_data == NULL) { -+ PRINTM(ERROR, "uap_hostcmd_ioctl() corrupt data\n"); -+ LEAVE(); -+ return -EFAULT; -+ } -+ if (copy_from_user(&buf_len, req->ifr_data, sizeof(buf_len))) { -+ PRINTM(ERROR, "Copy from user failed\n"); -+ LEAVE(); -+ return -EFAULT; -+ } -+ memset(&head, 0, sizeof(HostCmd_HEADER)); -+ /* Get the command size from user space */ -+ if (copy_from_user -+ (&head, req->ifr_data + sizeof(buf_len), sizeof(HostCmd_HEADER))) { -+ PRINTM(ERROR, "Copy from user failed\n"); -+ LEAVE(); -+ return -EFAULT; -+ } -+ head.Size = uap_le16_to_cpu(head.Size); -+ if (head.Size > MRVDRV_SIZE_OF_CMD_BUFFER) { -+ PRINTM(ERROR, "CmdSize too big=%d\n", head.Size); -+ LEAVE(); -+ return -EFAULT; -+ } -+ PRINTM(CMND, "ioctl: hostcmd=%x, size=%d,buf_len=%d\n", head.Command, -+ head.Size, buf_len); -+ skb = dev_alloc_skb(head.Size + INTF_HEADER_LEN); -+ if (!skb) { -+ PRINTM(ERROR, "No free skb\n"); -+ LEAVE(); -+ return -ENOMEM; -+ } -+ -+ /* Get the command from user space */ -+ if (copy_from_user -+ (skb->data + INTF_HEADER_LEN, req->ifr_data + sizeof(buf_len), -+ head.Size)) { -+ PRINTM(ERROR, "Copy from user failed\n"); -+ LEAVE(); -+ return -EFAULT; -+ } -+ skb_put(skb, head.Size + INTF_HEADER_LEN); -+ if (UAP_STATUS_SUCCESS != -+ uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP)) { -+ PRINTM(ERROR, "Fail to process cmd\n"); -+ LEAVE(); -+ return -EFAULT; -+ } -+ if (!Adapter->CmdSize) { -+ PRINTM(ERROR, "Cmd Size is 0\n"); -+ LEAVE(); -+ return -EFAULT; -+ } -+ if (Adapter->CmdSize > buf_len) { -+ PRINTM(ERROR, "buf_len is too small\n"); -+ LEAVE(); -+ return -EFAULT; -+ } -+ /* Copy to user */ -+ if (copy_to_user -+ (req->ifr_data + sizeof(buf_len), Adapter->CmdBuf, Adapter->CmdSize)) { -+ PRINTM(ERROR, "Copy to user failed!\n"); -+ LEAVE(); -+ return -EFAULT; -+ } -+ LEAVE(); -+ return ret; -+} -+ -+/** -+ * @brief uap power mode ioctl handler -+ * -+ * @param dev A pointer to net_device structure -+ * @param req A pointer to ifreq structure -+ * @return UAP_STATUS_SUCCESS --success, otherwise fail -+ */ -+static int -+uap_power_mode_ioctl(struct net_device *dev, struct ifreq *req) -+{ -+ ps_mgmt pm_cfg; -+ int ret = UAP_STATUS_SUCCESS; -+ uap_private *priv = (uap_private *) netdev_priv(dev); -+ uap_adapter *Adapter = priv->adapter; -+ struct sk_buff *skb = NULL; -+ HostCmd_DS_COMMAND *cmd; -+ u32 CmdSize; -+ u8 *tlv = NULL; -+ MrvlIEtypes_sleep_param_t *sleep_tlv = NULL; -+ MrvlIEtypes_inact_sleep_param_t *inact_tlv = NULL; -+ u16 tlv_buf_left = 0; -+ MrvlIEtypesHeader_t *tlvbuf = NULL; -+ u16 tlv_type = 0; -+ u16 tlv_len = 0; -+ -+ ENTER(); -+ -+ /* Sanity check */ -+ if (req->ifr_data == NULL) { -+ PRINTM(ERROR, "uap_power_mode_ioctl() corrupt data\n"); -+ LEAVE(); -+ return -EFAULT; -+ } -+ -+ memset(&pm_cfg, 0, sizeof(ps_mgmt)); -+ if (copy_from_user(&pm_cfg, req->ifr_data, sizeof(ps_mgmt))) { -+ PRINTM(ERROR, "Copy from user failed\n"); -+ LEAVE(); -+ return -EFAULT; -+ } -+ PRINTM(CMND, -+ "ioctl power: flag=0x%x ps_mode=%d ctrl_bitmap=%d min_sleep=%d max_sleep=%d " -+ "inact_to=%d min_awake=%d max_awake=%d\n", pm_cfg.flags, -+ (int) pm_cfg.ps_mode, (int) pm_cfg.sleep_param.ctrl_bitmap, -+ (int) pm_cfg.sleep_param.min_sleep, -+ (int) pm_cfg.sleep_param.max_sleep, -+ (int) pm_cfg.inact_param.inactivity_to, -+ (int) pm_cfg.inact_param.min_awake, -+ (int) pm_cfg.inact_param.max_awake); -+ -+ if (pm_cfg. -+ flags & ~(PS_FLAG_PS_MODE | PS_FLAG_SLEEP_PARAM | -+ PS_FLAG_INACT_SLEEP_PARAM)) { -+ PRINTM(ERROR, "Invalid parameter: flags = 0x%x\n", pm_cfg.flags); -+ ret = -EINVAL; -+ goto done; -+ } -+ if (pm_cfg.ps_mode > PS_MODE_INACTIVITY) { -+ PRINTM(ERROR, "Invalid parameter: ps_mode = %d\n", (int) pm_cfg.flags); -+ ret = -EINVAL; -+ goto done; -+ } -+ -+ skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER); -+ if (!skb) { -+ PRINTM(INFO, "No free skb\n"); -+ ret = -ENOMEM; -+ goto done; -+ } -+ -+ CmdSize = S_DS_GEN + sizeof(HostCmd_DS_POWER_MGMT_EXT); -+ -+ cmd = (HostCmd_DS_COMMAND *) (skb->data + INTF_HEADER_LEN); -+ cmd->Command = uap_cpu_to_le16(HOST_CMD_POWER_MGMT_EXT); -+ if (!pm_cfg.flags) { -+ cmd->params.pm_cfg.action = uap_cpu_to_le16(ACTION_GET); -+ } else { -+ cmd->params.pm_cfg.action = uap_cpu_to_le16(ACTION_SET); -+ cmd->params.pm_cfg.power_mode = uap_cpu_to_le16(pm_cfg.ps_mode); -+ tlv = (u8 *) & cmd->params.pm_cfg + sizeof(HostCmd_DS_POWER_MGMT_EXT); -+ -+ if ((pm_cfg.ps_mode) && (pm_cfg.flags & PS_FLAG_SLEEP_PARAM)) { -+ sleep_tlv = (MrvlIEtypes_sleep_param_t *) tlv; -+ sleep_tlv->header.Type = uap_cpu_to_le16(TLV_TYPE_AP_SLEEP_PARAM); -+ sleep_tlv->header.Len = -+ uap_cpu_to_le16(sizeof(MrvlIEtypes_sleep_param_t) - -+ sizeof(MrvlIEtypesHeader_t)); -+ sleep_tlv->ctrl_bitmap = -+ uap_cpu_to_le32(pm_cfg.sleep_param.ctrl_bitmap); -+ sleep_tlv->min_sleep = -+ uap_cpu_to_le32(pm_cfg.sleep_param.min_sleep); -+ sleep_tlv->max_sleep = -+ uap_cpu_to_le32(pm_cfg.sleep_param.max_sleep); -+ CmdSize += sizeof(MrvlIEtypes_sleep_param_t); -+ tlv += sizeof(MrvlIEtypes_sleep_param_t); -+ } -+ if ((pm_cfg.ps_mode == PS_MODE_INACTIVITY) && -+ (pm_cfg.flags & PS_FLAG_INACT_SLEEP_PARAM)) { -+ inact_tlv = (MrvlIEtypes_inact_sleep_param_t *) tlv; -+ inact_tlv->header.Type = -+ uap_cpu_to_le16(TLV_TYPE_AP_INACT_SLEEP_PARAM); -+ inact_tlv->header.Len = -+ uap_cpu_to_le16(sizeof(MrvlIEtypes_inact_sleep_param_t) - -+ sizeof(MrvlIEtypesHeader_t)); -+ inact_tlv->inactivity_to = -+ uap_cpu_to_le32(pm_cfg.inact_param.inactivity_to); -+ inact_tlv->min_awake = -+ uap_cpu_to_le32(pm_cfg.inact_param.min_awake); -+ inact_tlv->max_awake = -+ uap_cpu_to_le32(pm_cfg.inact_param.max_awake); -+ CmdSize += sizeof(MrvlIEtypes_inact_sleep_param_t); -+ tlv += sizeof(MrvlIEtypes_inact_sleep_param_t); -+ } -+ } -+ cmd->Size = uap_cpu_to_le16(CmdSize); -+ skb_put(skb, CmdSize + INTF_HEADER_LEN); -+ if (UAP_STATUS_SUCCESS != -+ uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP)) { -+ PRINTM(ERROR, "Fail to process cmd POWER_MODE\n"); -+ ret = -EFAULT; -+ goto done; -+ } -+ if (!Adapter->CmdSize) { -+ PRINTM(ERROR, "Cmd Size is 0\n"); -+ ret = -EFAULT; -+ goto done; -+ } -+ cmd = (HostCmd_DS_COMMAND *) Adapter->CmdBuf; -+ cmd->Result = uap_le16_to_cpu(cmd->Result); -+ if (cmd->Result != UAP_STATUS_SUCCESS) { -+ PRINTM(ERROR, "HOST_CMD_APCMD_POWER_MODE fail=%x\n", cmd->Result); -+ ret = -EFAULT; -+ goto done; -+ } -+ if (pm_cfg.flags) { -+ Adapter->psmode = uap_le16_to_cpu(cmd->params.pm_cfg.power_mode); -+ } else { -+ pm_cfg.flags = PS_FLAG_PS_MODE; -+ pm_cfg.ps_mode = uap_le16_to_cpu(cmd->params.pm_cfg.power_mode); -+ tlv_buf_left = -+ cmd->Size - (sizeof(HostCmd_DS_POWER_MGMT_EXT) + S_DS_GEN); -+ tlvbuf = -+ (MrvlIEtypesHeader_t *) ((u8 *) & cmd->params.pm_cfg + -+ sizeof(HostCmd_DS_POWER_MGMT_EXT)); -+ while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) { -+ tlv_type = uap_le16_to_cpu(tlvbuf->Type); -+ tlv_len = uap_le16_to_cpu(tlvbuf->Len); -+ switch (tlv_type) { -+ case TLV_TYPE_AP_SLEEP_PARAM: -+ sleep_tlv = (MrvlIEtypes_sleep_param_t *) tlvbuf; -+ pm_cfg.flags |= PS_FLAG_SLEEP_PARAM; -+ pm_cfg.sleep_param.ctrl_bitmap = -+ uap_le32_to_cpu(sleep_tlv->ctrl_bitmap); -+ pm_cfg.sleep_param.min_sleep = -+ uap_le32_to_cpu(sleep_tlv->min_sleep); -+ pm_cfg.sleep_param.max_sleep = -+ uap_le32_to_cpu(sleep_tlv->max_sleep); -+ break; -+ case TLV_TYPE_AP_INACT_SLEEP_PARAM: -+ inact_tlv = (MrvlIEtypes_inact_sleep_param_t *) tlvbuf; -+ pm_cfg.flags |= PS_FLAG_INACT_SLEEP_PARAM; -+ pm_cfg.inact_param.inactivity_to = -+ uap_le32_to_cpu(inact_tlv->inactivity_to); -+ pm_cfg.inact_param.min_awake = -+ uap_le32_to_cpu(inact_tlv->min_awake); -+ pm_cfg.inact_param.max_awake = -+ uap_le32_to_cpu(inact_tlv->max_awake); -+ break; -+ } -+ tlv_buf_left -= tlv_len + sizeof(MrvlIEtypesHeader_t); -+ tlvbuf = -+ (MrvlIEtypesHeader_t *) ((u8 *) tlvbuf + tlv_len + -+ sizeof(MrvlIEtypesHeader_t)); -+ } -+ /* Copy to user */ -+ if (copy_to_user(req->ifr_data, &pm_cfg, sizeof(ps_mgmt))) { -+ PRINTM(ERROR, "Copy to user failed!\n"); -+ LEAVE(); -+ return -EFAULT; -+ } -+ } -+ done: -+ LEAVE(); -+ return ret; -+} -+ -+/** -+ * @brief This function send bss_stop command to firmware -+ * -+ * @param priv A pointer to uap_private structure -+ * @return UAP_STATUS_SUCCESS on success, otherwise failure code -+ */ -+static int -+uap_bss_stop(uap_private * priv) -+{ -+ int ret = UAP_STATUS_SUCCESS; -+ u32 CmdSize; -+ HostCmd_DS_GEN *cmd; -+ uap_adapter *Adapter = priv->adapter; -+ struct sk_buff *skb; -+ ENTER(); -+ if (Adapter->HardwareStatus != HWReady) { -+ PRINTM(ERROR, "uap_bss_stop:Hardware is not ready!\n"); -+ ret = -EFAULT; -+ goto done; -+ } -+ skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER); -+ if (!skb) { -+ PRINTM(ERROR, "No free skb\n"); -+ ret = -ENOMEM; -+ goto done; -+ } -+ CmdSize = sizeof(HostCmd_DS_GEN); -+ cmd = (HostCmd_DS_GEN *) (skb->data + INTF_HEADER_LEN); -+ cmd->Command = uap_cpu_to_le16(HOST_CMD_APCMD_BSS_STOP); -+ cmd->Size = uap_cpu_to_le16(CmdSize); -+ skb_put(skb, CmdSize + INTF_HEADER_LEN); -+ PRINTM(CMND, "APCMD_BSS_STOP\n"); -+ if (UAP_STATUS_SUCCESS != -+ uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP_TIMEOUT)) { -+ PRINTM(ERROR, "Fail to process cmd BSS_STOP\n"); -+ ret = -EFAULT; -+ goto done; -+ } -+ done: -+ LEAVE(); -+ return ret; -+} -+ -+/******************************************************** -+ Global Functions -+********************************************************/ -+/** -+ * @brief This function send soft_reset command to firmware -+ * -+ * @param priv A pointer to uap_private structure -+ * @return UAP_STATUS_SUCCESS on success, otherwise failure code -+ */ -+int -+uap_soft_reset(uap_private * priv) -+{ -+ int ret = UAP_STATUS_SUCCESS; -+ u32 CmdSize; -+ HostCmd_DS_GEN *cmd; -+ uap_adapter *Adapter = priv->adapter; -+ struct sk_buff *skb; -+ ENTER(); -+ ret = uap_bss_stop(priv); -+ if (ret != UAP_STATUS_SUCCESS) -+ goto done; -+ skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER); -+ if (!skb) { -+ PRINTM(ERROR, "No free skb\n"); -+ ret = -ENOMEM; -+ goto done; -+ } -+ CmdSize = sizeof(HostCmd_DS_GEN); -+ cmd = (HostCmd_DS_GEN *) (skb->data + INTF_HEADER_LEN); -+ cmd->Command = uap_cpu_to_le16(HOST_CMD_APCMD_SOFT_RESET); -+ cmd->Size = uap_cpu_to_le16(CmdSize); -+ skb_put(skb, CmdSize + INTF_HEADER_LEN); -+ PRINTM(CMND, "APCMD_SOFT_RESET\n"); -+ if (UAP_STATUS_SUCCESS != -+ uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORSEND)) { -+ PRINTM(ERROR, "Fail to process cmd SOFT_RESET\n"); -+ ret = -EFAULT; -+ goto done; -+ } -+ Adapter->SurpriseRemoved = TRUE; -+ /* delay to allow hardware complete reset */ -+ os_sched_timeout(5); -+ if (priv->MediaConnected == TRUE) { -+ os_stop_queue(priv); -+ os_carrier_off(priv); -+ priv->MediaConnected = FALSE; -+ } -+ Adapter->CmdSize = 0; -+ Adapter->CmdWaitQWoken = TRUE; -+ wake_up_interruptible(&Adapter->cmdwait_q); -+ skb_queue_purge(&priv->adapter->tx_queue); -+ skb_queue_purge(&priv->adapter->cmd_queue); -+ done: -+ LEAVE(); -+ return ret; -+} -+ -+/** -+ * @brief This function processes received packet and forwards it -+ * to kernel/upper layer -+ * -+ * @param priv A pointer to uap_private -+ * @param skb A pointer to skb which includes the received packet -+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE -+ */ -+int -+uap_process_rx_packet(uap_private * priv, struct sk_buff *skb) -+{ -+ int ret = UAP_STATUS_SUCCESS; -+ RxPD *pRxPD; -+ ENTER(); -+ priv->adapter->ps_state = PS_STATE_AWAKE; -+ pRxPD = (RxPD *) skb->data; -+ endian_convert_RxPD(pRxPD); -+ DBG_HEXDUMP(DAT_D, "Rx", skb->data, MIN(skb->len, DATA_DUMP_LEN)); -+ skb_pull(skb, pRxPD->RxPktOffset); -+ priv->stats.rx_packets++; -+ priv->stats.rx_bytes += skb->len; -+ os_upload_rx_packet(priv, skb); -+ LEAVE(); -+ return ret; -+} -+ -+/** -+ * @brief This function opens the network device -+ * -+ * @param dev A pointer to net_device structure -+ * @return UAP_STATUS_SUCCESS -+ */ -+static int -+uap_open(struct net_device *dev) -+{ -+ uap_private *priv = (uap_private *) (uap_private *) netdev_priv(dev); -+ uap_adapter *Adapter = priv->adapter; -+ int i = 0; -+ -+ ENTER(); -+ -+ /* On some systems the device open handler will be called before HW ready. */ -+ /* Use the following flag check and wait function to work around the issue. */ -+ while ((Adapter->HardwareStatus != HWReady) && -+ (i < MAX_WAIT_DEVICE_READY_COUNT)) { -+ i++; -+ os_sched_timeout(100); -+ } -+ if (i >= MAX_WAIT_DEVICE_READY_COUNT) { -+ PRINTM(FATAL, "HW not ready, uap_open() return failure\n"); -+ LEAVE(); -+ return UAP_STATUS_FAILURE; -+ } -+ -+ if (MODULE_GET == 0) -+ return UAP_STATUS_FAILURE; -+ -+ priv->open = TRUE; -+ if (priv->MediaConnected == TRUE) { -+ os_carrier_on(priv); -+ os_start_queue(priv); -+ } else { -+ os_stop_queue(priv); -+ os_carrier_off(priv); -+ } -+ LEAVE(); -+ return UAP_STATUS_SUCCESS; -+} -+ -+/** -+ * @brief This function closes the network device -+ * -+ * @param dev A pointer to net_device structure -+ * @return UAP_STATUS_SUCCESS -+ */ -+static int -+uap_close(struct net_device *dev) -+{ -+ uap_private *priv = (uap_private *) netdev_priv(dev); -+ -+ ENTER(); -+ skb_queue_purge(&priv->adapter->tx_queue); -+ os_stop_queue(priv); -+ os_carrier_off(priv); -+ -+ MODULE_PUT; -+ priv->open = FALSE; -+ LEAVE(); -+ return UAP_STATUS_SUCCESS; -+} -+ -+/** -+ * @brief This function returns the network statistics -+ * -+ * @param dev A pointer to uap_private structure -+ * @return A pointer to net_device_stats structure -+ */ -+static struct net_device_stats * -+uap_get_stats(struct net_device *dev) -+{ -+ uap_private *priv = (uap_private *) netdev_priv(dev); -+ -+ return &priv->stats; -+} -+ -+/** -+ * @brief This function sets the MAC address to firmware. -+ * -+ * @param dev A pointer to uap_private structure -+ * @param addr MAC address to set -+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE -+ */ -+static int -+uap_set_mac_address(struct net_device *dev, void *addr) -+{ -+ int ret = UAP_STATUS_SUCCESS; -+ uap_private *priv = (uap_private *) netdev_priv(dev); -+ struct sockaddr *pHwAddr = (struct sockaddr *) addr; -+ u32 CmdSize; -+ HostCmd_DS_COMMAND *cmd; -+ MrvlIEtypes_MacAddr_t *pMacAddrTlv; -+ uap_adapter *Adapter = priv->adapter; -+ struct sk_buff *skb; -+ -+ ENTER(); -+ -+ /* Dump MAC address */ -+ DBG_HEXDUMP(CMD_D, "Original MAC addr", dev->dev_addr, ETH_ALEN); -+ DBG_HEXDUMP(CMD_D, "New MAC addr", pHwAddr->sa_data, ETH_ALEN); -+ if (priv->open && (priv->MediaConnected == TRUE)) { -+ os_carrier_on(priv); -+ os_start_queue(priv); -+ } -+ skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER); -+ if (!skb) { -+ PRINTM(ERROR, "No free skb\n"); -+ LEAVE(); -+ return -ENOMEM; -+ } -+ CmdSize = -+ S_DS_GEN + sizeof(HostCmd_SYS_CONFIG) + sizeof(MrvlIEtypes_MacAddr_t); -+ cmd = (HostCmd_DS_COMMAND *) (skb->data + INTF_HEADER_LEN); -+ cmd->Command = uap_cpu_to_le16(HOST_CMD_APCMD_SYS_CONFIGURE); -+ cmd->Size = uap_cpu_to_le16(CmdSize); -+ cmd->params.sys_config.Action = uap_cpu_to_le16(ACTION_SET); -+ pMacAddrTlv = -+ (MrvlIEtypes_MacAddr_t *) ((u8 *) cmd + S_DS_GEN + -+ sizeof(HostCmd_SYS_CONFIG)); -+ pMacAddrTlv->Header.Type = uap_cpu_to_le16(MRVL_AP_MAC_ADDRESS_TLV_ID); -+ pMacAddrTlv->Header.Len = uap_cpu_to_le16(ETH_ALEN); -+ memcpy(pMacAddrTlv->ApMacAddr, pHwAddr->sa_data, ETH_ALEN); -+ skb_put(skb, CmdSize + INTF_HEADER_LEN); -+ PRINTM(CMND, "set_mac_address\n"); -+ if (UAP_STATUS_SUCCESS != -+ uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP_TIMEOUT)) { -+ PRINTM(ERROR, "Fail to set mac address\n"); -+ LEAVE(); -+ return -EFAULT; -+ } -+ if (!Adapter->CmdSize) { -+ PRINTM(ERROR, "Cmd Size is 0\n"); -+ LEAVE(); -+ return -EFAULT; -+ } -+ cmd = (HostCmd_DS_COMMAND *) Adapter->CmdBuf; -+ cmd->Result = uap_cpu_to_le16(cmd->Result); -+ if (cmd->Result != UAP_STATUS_SUCCESS) { -+ PRINTM(ERROR, "set mac addrress fail,cmd result=%x\n", cmd->Result); -+ ret = -EFAULT; -+ } else -+ memcpy(dev->dev_addr, pHwAddr->sa_data, ETH_ALEN); -+ LEAVE(); -+ return ret; -+} -+ -+/** -+ * @brief This function sets multicast addresses to firmware -+ * -+ * @param dev A pointer to net_device structure -+ * @return n/a -+ */ -+static void -+uap_set_multicast_list(struct net_device *dev) -+{ -+ ENTER(); -+#warning uap_set_multicast_list not implemented. Expect problems with IPv6. -+ LEAVE(); -+} -+ -+/** -+ * @brief This function handles the timeout of packet -+ * transmission -+ * -+ * @param dev A pointer to net_device structure -+ * @return n/a -+ */ -+static void -+uap_tx_timeout(struct net_device *dev) -+{ -+ uap_private *priv = (uap_private *) netdev_priv(dev); -+ -+ ENTER(); -+ -+ PRINTM(DATA, "Tx timeout\n"); -+ UpdateTransStart(dev); -+ priv->num_tx_timeout++; -+ priv->adapter->IntCounter++; -+ wake_up_interruptible(&priv->MainThread.waitQ); -+ -+ LEAVE(); -+} -+ -+/** -+ * @brief This function handles packet transmission -+ * -+ * @param skb A pointer to sk_buff structure -+ * @param dev A pointer to net_device structure -+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE -+ */ -+static int -+uap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) -+{ -+ uap_private *priv = (uap_private *) netdev_priv(dev); -+ int ret = UAP_STATUS_SUCCESS; -+ -+ ENTER(); -+ PRINTM(DATA, "Data <= kernel\n"); -+ DBG_HEXDUMP(DAT_D, "Tx", skb->data, MIN(skb->len, DATA_DUMP_LEN)); -+ /* skb sanity check */ -+ if (!skb->len || (skb->len > MRVDRV_MAXIMUM_ETH_PACKET_SIZE)) { -+ PRINTM(ERROR, "Tx Error: Bad skb length %d : %d\n", skb->len, -+ MRVDRV_MAXIMUM_ETH_PACKET_SIZE); -+ priv->stats.tx_dropped++; -+ kfree(skb); -+ goto done; -+ } -+ skb_queue_tail(&priv->adapter->tx_queue, skb); -+ wake_up_interruptible(&priv->MainThread.waitQ); -+ if (skb_queue_len(&priv->adapter->tx_queue) > TX_HIGH_WATERMARK) { -+ UpdateTransStart(dev); -+ os_stop_queue(priv); -+ } -+ done: -+ LEAVE(); -+ return ret; -+} -+ -+/** -+ * @brief ioctl function - entry point -+ * -+ * @param dev A pointer to net_device structure -+ * @param req A pointer to ifreq structure -+ * @param cmd command -+ * @return UAP_STATUS_SUCCESS--success, otherwise fail -+ */ -+static int -+uap_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd) -+{ -+ int ret = UAP_STATUS_SUCCESS; -+ -+ ENTER(); -+ -+ PRINTM(CMND, "uap_do_ioctl: ioctl cmd = 0x%x\n", cmd); -+ -+ switch (cmd) { -+ case UAPHOSTCMD: -+ ret = uap_hostcmd_ioctl(dev, req); -+ break; -+ case UAP_POWER_MODE: -+ ret = uap_power_mode_ioctl(dev, req); -+ break; -+ default: -+ ret = -EINVAL; -+ break; -+ } -+ -+ LEAVE(); -+ return ret; -+} -+ -+/** -+ * @brief This function handles events generated by firmware -+ * -+ * @param priv A pointer to uap_private structure -+ * @param payload A pointer to payload buffer -+ * @param len Length of the payload -+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE -+ */ -+int -+uap_process_event(uap_private * priv, u8 * payload, uint len) -+{ -+ int ret = UAP_STATUS_SUCCESS; -+ uap_adapter *Adapter = priv->adapter; -+ struct sk_buff *skb = NULL; -+ struct nlmsghdr *nlh = NULL; -+ struct sock *sk = Adapter->nl_sk; -+ AP_Event *pEvent; -+ -+ ENTER(); -+ Adapter->ps_state = PS_STATE_AWAKE; -+ if (len > NL_MAX_PAYLOAD) { -+ PRINTM(ERROR, "event size is too big!!! len=%d\n", len); -+ ret = UAP_STATUS_FAILURE; -+ goto done; -+ } -+ pEvent = (AP_Event *) payload; -+ PRINTM(CMND, "Event: %d\n", pEvent->EventId); -+ switch (pEvent->EventId) { -+ case MICRO_AP_EV_ID_BSS_START: -+ memcpy(priv->uap_dev.netdev->dev_addr, pEvent->MacAddr, ETH_ALEN); -+ DBG_HEXDUMP(CMD_D, "BSS MAC addr", priv->uap_dev.netdev->dev_addr, -+ ETH_ALEN); -+ break; -+ case MICRO_AP_EV_BSS_ACTIVE: -+ // carrier on -+ priv->MediaConnected = TRUE; -+ os_carrier_on(priv); -+ os_start_queue(priv); -+ break; -+ case MICRO_AP_EV_BSS_IDLE: -+ os_stop_queue(priv); -+ os_carrier_off(priv); -+ priv->MediaConnected = FALSE; -+ break; -+ case EVENT_PS_AWAKE: -+ PRINTM(CMND, "UAP: PS_AWAKE\n"); -+ Adapter->ps_state = PS_STATE_AWAKE; -+ Adapter->WakeupTries = 0; -+ break; -+ case EVENT_PS_SLEEP: -+ PRINTM(CMND, "UAP: PS_SLEEP\n"); -+ Adapter->ps_state = PS_STATE_PRE_SLEEP; -+ break; -+ default: -+ break; -+ } -+ if ((pEvent->EventId == EVENT_PS_AWAKE) || -+ (pEvent->EventId == EVENT_PS_SLEEP)) -+ goto done; -+ if (sk) { -+ /* Allocate skb */ -+ if (!(skb = alloc_skb(NLMSG_SPACE(NL_MAX_PAYLOAD), GFP_ATOMIC))) { -+ PRINTM(ERROR, "Could not allocate skb for netlink.\n"); -+ ret = UAP_STATUS_FAILURE; -+ goto done; -+ } -+ nlh = (struct nlmsghdr *) skb->data; -+ nlh->nlmsg_len = NLMSG_SPACE(len); -+ -+ /* From kernel */ -+ nlh->nlmsg_pid = 0; -+ nlh->nlmsg_flags = 0; -+ -+ /* Data */ -+ skb_put(skb, nlh->nlmsg_len); -+ memcpy(NLMSG_DATA(nlh), payload, len); -+ -+ /* From Kernel */ -+ NETLINK_CB(skb).pid = 0; -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -+ /* Multicast message */ -+ NETLINK_CB(skb).dst_pid = 0; -+#endif -+ -+ /* Multicast group number */ -+ NETLINK_CB(skb).dst_group = NL_MULTICAST_GROUP; -+ -+ /* Send message */ -+ netlink_broadcast(sk, skb, 0, NL_MULTICAST_GROUP, GFP_KERNEL); -+ -+ ret = UAP_STATUS_SUCCESS; -+ } else { -+ PRINTM(ERROR, "Could not send event through NETLINK. Link down.\n"); -+ ret = UAP_STATUS_FAILURE; -+ } -+ done: -+ LEAVE(); -+ return ret; -+} -+ -+/** -+ * @brief This function handles the interrupt. it will change PS -+ * state if applicable. it will wake up main_thread to handle -+ * the interrupt event as well. -+ * -+ * @param priv A pointer to uap_private structure -+ * @return n/a -+ */ -+void -+uap_interrupt(uap_private * priv) -+{ -+ ENTER(); -+ priv->adapter->IntCounter++; -+ priv->adapter->WakeupTries = 0; -+ PRINTM(INFO, "*\n"); -+ wake_up_interruptible(&priv->MainThread.waitQ); -+ -+ LEAVE(); -+ -+} -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) -+/** Network device handlers */ -+static const struct net_device_ops uap_netdev_ops = { -+ .ndo_open = uap_open, -+ .ndo_start_xmit = uap_hard_start_xmit, -+ .ndo_stop = uap_close, -+ .ndo_do_ioctl = uap_do_ioctl, -+ .ndo_set_mac_address = uap_set_mac_address, -+ .ndo_tx_timeout = uap_tx_timeout, -+ .ndo_get_stats = uap_get_stats, -+ .ndo_set_multicast_list = uap_set_multicast_list, -+}; -+#endif -+ -+/** -+ * @brief This function adds the card. it will probe the -+ * card, allocate the uap_priv and initialize the device. -+ * -+ * @param card A pointer to card -+ * @return A pointer to uap_private structure -+ */ -+uap_private * -+uap_add_card(void *card) -+{ -+ struct net_device *dev = NULL; -+ uap_private *priv = NULL; -+ -+ ENTER(); -+ -+ if (OS_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem)) -+ goto exit_sem_err; -+ -+ /* Allocate an Ethernet device */ -+ if (!(dev = alloc_etherdev(sizeof(uap_private)))) { -+ PRINTM(FATAL, "Init ethernet device failed!\n"); -+ goto error; -+ } -+ priv = (uap_private *) netdev_priv(dev); -+ -+ /* Allocate name */ -+ if (dev_alloc_name(dev, "uap%d") < 0) { -+ PRINTM(ERROR, "Could not allocate device name!\n"); -+ goto error; -+ } -+ -+ /* Allocate buffer for uap_adapter */ -+ if (!(priv->adapter = kmalloc(sizeof(uap_adapter), GFP_KERNEL))) { -+ PRINTM(FATAL, "Allocate buffer for uap_adapter failed!\n"); -+ goto error; -+ } -+ memset(priv->adapter, 0, sizeof(uap_adapter)); -+ -+ priv->uap_dev.netdev = dev; -+ priv->uap_dev.card = card; -+ priv->MediaConnected = FALSE; -+ uappriv = priv; -+ ((struct sdio_mmc_card *) card)->priv = priv; -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) -+ SET_MODULE_OWNER(dev); -+#endif -+ -+ /* Setup the OS Interface to our functions */ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) -+ dev->open = uap_open; -+ dev->stop = uap_close; -+ dev->hard_start_xmit = uap_hard_start_xmit; -+ dev->tx_timeout = uap_tx_timeout; -+ dev->get_stats = uap_get_stats; -+ dev->do_ioctl = uap_do_ioctl; -+ dev->set_mac_address = uap_set_mac_address; -+ dev->set_multicast_list = uap_set_multicast_list; -+#else -+ dev->netdev_ops = &uap_netdev_ops; -+#endif -+ dev->watchdog_timeo = MRVDRV_DEFAULT_WATCHDOG_TIMEOUT; -+ dev->hard_header_len += sizeof(TxPD) + INTF_HEADER_LEN; -+ dev->hard_header_len += HEADER_ALIGNMENT; -+#define NETIF_F_DYNALLOC 16 -+ dev->features |= NETIF_F_DYNALLOC; -+ dev->flags |= IFF_BROADCAST | IFF_MULTICAST; -+ -+ /* Init SW */ -+ if (uap_init_sw(priv)) { -+ PRINTM(FATAL, "Software Init Failed\n"); -+ goto error; -+ } -+ -+ PRINTM(INFO, "Starting kthread...\n"); -+ priv->MainThread.priv = priv; -+ spin_lock_init(&priv->driver_lock); -+ uap_create_thread(uap_service_main_thread, &priv->MainThread, -+ "uap_main_service"); -+ while (priv->MainThread.pid == 0) { -+ os_sched_timeout(2); -+ } -+ -+ /* Register the device */ -+ if (sbi_register_dev(priv) < 0) { -+ PRINTM(FATAL, "Failed to register uap device!\n"); -+ goto err_registerdev; -+ } -+#ifdef FW_DNLD_NEEDED -+ SET_NETDEV_DEV(dev, priv->hotplug_device); -+#endif -+ -+ /* Init FW and HW */ -+ if (uap_init_fw(priv)) { -+ PRINTM(FATAL, "Firmware Init Failed\n"); -+ goto err_init_fw; -+ } -+ -+ priv->uap_dev.cmd_sent = FALSE; -+ priv->uap_dev.data_sent = FALSE; -+ -+ /* Get mac address from firmware */ -+ if (uap_get_mac_address(priv)) { -+ PRINTM(FATAL, "Fail to get mac address\n"); -+ goto err_init_fw; -+ } -+ /* Register network device */ -+ if (register_netdev(dev)) { -+ printk(KERN_ERR "Cannot register network device!\n"); -+ goto err_init_fw; -+ } -+#ifdef CONFIG_PROC_FS -+ uap_proc_entry(priv, dev); -+ uap_debug_entry(priv, dev); -+#endif /* CPNFIG_PROC_FS */ -+ OS_REL_SEMAPHORE(&AddRemoveCardSem); -+ -+ LEAVE(); -+ return priv; -+ err_init_fw: -+ sbi_unregister_dev(priv); -+ err_registerdev: -+ ((struct sdio_mmc_card *) card)->priv = NULL; -+ /* Stop the thread servicing the interrupts */ -+ priv->adapter->SurpriseRemoved = TRUE; -+ wake_up_interruptible(&priv->MainThread.waitQ); -+ while (priv->MainThread.pid) { -+ os_sched_timeout(1); -+ } -+ error: -+ if (dev) { -+ if (dev->reg_state == NETREG_REGISTERED) -+ unregister_netdev(dev); -+ if (priv->adapter) -+ uap_free_adapter(priv); -+ free_netdev(dev); -+ uappriv = NULL; -+ } -+ OS_REL_SEMAPHORE(&AddRemoveCardSem); -+ exit_sem_err: -+ LEAVE(); -+ return NULL; -+} -+ -+/** -+ * @brief This function removes the card. -+ * -+ * @param card A pointer to card -+ * @return UAP_STATUS_SUCCESS -+ */ -+int -+uap_remove_card(void *card) -+{ -+ uap_private *priv = uappriv; -+ uap_adapter *Adapter; -+ struct net_device *dev; -+ -+ ENTER(); -+ -+ if (OS_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem)) -+ goto exit_sem_err; -+ -+ if (!priv || !(Adapter = priv->adapter)) { -+ goto exit_remove; -+ } -+ Adapter->SurpriseRemoved = TRUE; -+ if (Adapter->cmd_pending == TRUE) { -+ /* Wake up cmd Q */ -+ Adapter->CmdWaitQWoken = TRUE; -+ wake_up_interruptible(&Adapter->cmdwait_q); -+ } -+ dev = priv->uap_dev.netdev; -+ if (priv->MediaConnected == TRUE) { -+ os_stop_queue(priv); -+ os_carrier_off(priv); -+ priv->MediaConnected = FALSE; -+ } -+ Adapter->CmdSize = 0; -+ Adapter->CmdWaitQWoken = TRUE; -+ wake_up_interruptible(&Adapter->cmdwait_q); -+ skb_queue_purge(&priv->adapter->tx_queue); -+ skb_queue_purge(&priv->adapter->cmd_queue); -+ -+ /* Disable interrupts on the card */ -+ sbi_disable_host_int(priv); -+ PRINTM(INFO, "netdev_finish_unregister: %s%s.\n", dev->name, -+ (dev->features & NETIF_F_DYNALLOC) ? "" : ", old style"); -+ unregister_netdev(dev); -+ PRINTM(INFO, "Unregister finish\n"); -+ wake_up_interruptible(&priv->MainThread.waitQ); -+ while (priv->MainThread.pid) { -+ os_sched_timeout(1); -+ } -+ -+ if ((Adapter->nl_sk) && ((Adapter->nl_sk)->sk_socket)) { -+ sock_release((Adapter->nl_sk)->sk_socket); -+ Adapter->nl_sk = NULL; -+ } -+#ifdef CONFIG_PROC_FS -+ uap_debug_remove(priv); -+ uap_proc_remove(priv); -+#endif -+ sbi_unregister_dev(priv); -+ PRINTM(INFO, "Free Adapter\n"); -+ uap_free_adapter(priv); -+ priv->uap_dev.netdev = NULL; -+ free_netdev(dev); -+ uappriv = NULL; -+ -+ exit_remove: -+ OS_REL_SEMAPHORE(&AddRemoveCardSem); -+ exit_sem_err: -+ LEAVE(); -+ return UAP_STATUS_SUCCESS; -+} -+ -+/** -+ * @brief This function initializes module. -+ * -+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE -+ */ -+static int __init -+uap_init_module(void) -+{ -+ int ret = UAP_STATUS_SUCCESS; -+ ENTER(); -+ -+ OS_INIT_SEMAPHORE(&AddRemoveCardSem); -+ ret = sbi_register(); -+ LEAVE(); -+ return ret; -+} -+ -+/** -+ * @brief This function cleans module -+ * -+ * @return n/a -+ */ -+static void __exit -+uap_cleanup_module(void) -+{ -+ ENTER(); -+ -+ if (OS_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem)) -+ goto exit_sem_err; -+ -+ if ((uappriv) && (uappriv->adapter)) { -+ uap_func_shutdown(uappriv); -+ } -+ OS_REL_SEMAPHORE(&AddRemoveCardSem); -+ exit_sem_err: -+ sbi_unregister(); -+ LEAVE(); -+} -+ -+module_init(uap_init_module); -+module_exit(uap_cleanup_module); -+module_param(helper_name, charp, 0); -+MODULE_PARM_DESC(helper_name, "Helper name"); -+module_param(fw_name, charp, 0); -+MODULE_PARM_DESC(fw_name, "Firmware name"); -+ -+MODULE_DESCRIPTION("M-UAP Driver"); -+MODULE_AUTHOR("Marvell International Ltd."); -+MODULE_VERSION(DRIVER_VERSION); -+MODULE_LICENSE("GPL"); -diff -Naupr linux-2.6.37/drivers/net/wireless/libertas_uap/uap_proc.c linux-2.6.37-new/drivers/net/wireless/libertas_uap/uap_proc.c ---- linux-2.6.37/drivers/net/wireless/libertas_uap/uap_proc.c 1969-12-31 17:00:00.000000000 -0700 -+++ linux-2.6.37-new/drivers/net/wireless/libertas_uap/uap_proc.c 2011-01-08 06:01:04.050835055 -0700 -@@ -0,0 +1,296 @@ -+/** @file uap_proc.c -+ * @brief This file contains functions for proc file. -+ * -+ * Copyright (C) 2008-2009, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available along with the File in the gpl.txt file or by writing to -+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ * -+ */ -+#ifdef CONFIG_PROC_FS -+#include "uap_headers.h" -+ -+/** /proc directory root */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) -+#define PROC_DIR NULL -+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) -+#define PROC_DIR &proc_root -+#else -+#define PROC_DIR proc_net -+#endif -+ -+/******************************************************** -+ Local Variables -+********************************************************/ -+ -+/******************************************************** -+ Global Variables -+********************************************************/ -+ -+/******************************************************** -+ Local Functions -+********************************************************/ -+ -+/** -+ * @brief proc read function -+ * -+ * @param page pointer to buffer -+ * @param start read data starting position -+ * @param offset offset -+ * @param count counter -+ * @param eof end of file flag -+ * @param data data to output -+ * @return number of output data -+ */ -+static int -+uap_proc_read(char *page, char **start, off_t offset, -+ int count, int *eof, void *data) -+{ -+ int i; -+ char *p = page; -+ struct net_device *netdev = data; -+ struct netdev_hw_addr *ha; -+ char fmt[64]; -+ uap_private *priv = (uap_private *) netdev_priv(netdev); -+ -+ if (offset != 0) { -+ *eof = 1; -+ goto exit; -+ } -+ -+ strcpy(fmt, DRIVER_VERSION); -+ -+ p += sprintf(p, "driver_name = " "\"uap\"\n"); -+ p += sprintf(p, "driver_version = %s-(FP%s)", fmt, FPNUM); -+ p += sprintf(p, "\nInterfaceName=\"%s\"\n", netdev->name); -+ p += sprintf(p, "State=\"%s\"\n", -+ ((priv->MediaConnected == -+ FALSE) ? "Disconnected" : "Connected")); -+ p += sprintf(p, "MACAddress=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n", -+ netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2], -+ netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]); -+ i = 0; -+ netdev_for_each_mc_addr(ha, netdev) { -+ ++i; -+ } -+ p += sprintf(p, "MCCount=\"%d\"\n", i); -+ -+ /* -+ * Put out the multicast list -+ */ -+ i = 0; -+ netdev_for_each_mc_addr(ha, netdev) { -+ p += sprintf(p, -+ "MCAddr[%d]=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n", -+ i++, -+ ha->addr[0], ha->addr[1], -+ ha->addr[2], ha->addr[3], -+ ha->addr[4], ha->addr[5]); -+ } -+ -+ p += sprintf(p, "num_tx_bytes = %lu\n", priv->stats.tx_bytes); -+ p += sprintf(p, "num_rx_bytes = %lu\n", priv->stats.rx_bytes); -+ p += sprintf(p, "num_tx_pkts = %lu\n", priv->stats.tx_packets); -+ p += sprintf(p, "num_rx_pkts = %lu\n", priv->stats.rx_packets); -+ p += sprintf(p, "num_tx_pkts_dropped = %lu\n", priv->stats.tx_dropped); -+ p += sprintf(p, "num_rx_pkts_dropped = %lu\n", priv->stats.rx_dropped); -+ p += sprintf(p, "num_tx_pkts_err = %lu\n", priv->stats.tx_errors); -+ p += sprintf(p, "num_rx_pkts_err = %lu\n", priv->stats.rx_errors); -+ p += sprintf(p, "num_tx_timeout = %u\n", priv->num_tx_timeout); -+ p += sprintf(p, "carrier %s\n", -+ ((netif_carrier_ok(priv->uap_dev.netdev)) ? "on" : "off")); -+ p += sprintf(p, "tx queue %s\n", -+ ((netif_queue_stopped(priv->uap_dev.netdev)) ? "stopped" : -+ "started")); -+ -+ exit: -+ return (p - page); -+} -+ -+/** -+ * @brief hwstatus proc write function -+ * -+ * @param f file pointer -+ * @param buf pointer to data buffer -+ * @param cnt data number to write -+ * @param data data to write -+ * @return number of data -+ */ -+static int -+uap_hwstatus_write(struct file *f, const char *buf, unsigned long cnt, -+ void *data) -+{ -+ struct net_device *netdev = data; -+ uap_private *priv = (uap_private *) netdev_priv(netdev); -+ char databuf[10]; -+ int hwstatus; -+ MODULE_GET; -+ if (cnt > 10) { -+ MODULE_PUT; -+ return cnt; -+ } -+ if (copy_from_user(databuf, buf, cnt)) { -+ MODULE_PUT; -+ return 0; -+ } -+ hwstatus = string_to_number(databuf); -+ switch (hwstatus) { -+ case HWReset: -+ PRINTM(MSG, "reset hw\n"); -+ uap_soft_reset(priv); -+ priv->adapter->HardwareStatus = HWReset; -+ break; -+ default: -+ break; -+ } -+ MODULE_PUT; -+ return cnt; -+} -+ -+/** -+ * @brief hwstatus proc read function -+ * -+ * @param page pointer to buffer -+ * @param s read data starting position -+ * @param off offset -+ * @param cnt counter -+ * @param eof end of file flag -+ * @param data data to output -+ * @return number of output data -+ */ -+static int -+uap_hwstatus_read(char *page, char **s, off_t off, int cnt, int *eof, -+ void *data) -+{ -+ char *p = page; -+ struct net_device *netdev = data; -+ uap_private *priv = (uap_private *) netdev_priv(netdev); -+ MODULE_GET; -+ p += sprintf(p, "%d\n", priv->adapter->HardwareStatus); -+ MODULE_PUT; -+ return p - page; -+} -+ -+/******************************************************** -+ Global Functions -+********************************************************/ -+/** -+ * @brief create uap proc file -+ * -+ * @param priv pointer uap_private -+ * @param dev pointer net_device -+ * @return N/A -+ */ -+void -+uap_proc_entry(uap_private * priv, struct net_device *dev) -+{ -+ struct proc_dir_entry *r = PROC_DIR; -+ -+ PRINTM(INFO, "Creating Proc Interface\n"); -+ /* Check if uap directory already exists */ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) -+ for (r = r->subdir; r; r = r->next) { -+ if (r->namelen && !strcmp("uap", r->name)) { -+ /* Directory exists */ -+ PRINTM(WARN, "proc directory already exists!\n"); -+ priv->proc_uap = r; -+ break; -+ } -+ } -+#endif -+ if (!priv->proc_uap) { -+ priv->proc_uap = proc_mkdir("uap", PROC_DIR); -+ if (!priv->proc_uap) -+ return; -+ else -+ atomic_set(&priv->proc_uap->count, 1); -+ } else { -+ atomic_inc(&priv->proc_uap->count); -+ } -+ priv->proc_entry = proc_mkdir(dev->name, priv->proc_uap); -+ -+ if (priv->proc_entry) { -+ r = create_proc_read_entry("info", 0, priv->proc_entry, uap_proc_read, -+ dev); -+ r = create_proc_entry("hwstatus", 0644, priv->proc_entry); -+ if (r) { -+ r->data = dev; -+ r->read_proc = uap_hwstatus_read; -+ r->write_proc = uap_hwstatus_write; -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) -+ r->owner = THIS_MODULE; -+#endif -+ } else -+ PRINTM(MSG, "Fail to create proc hwstatus\n"); -+ } -+} -+ -+/** -+ * @brief remove proc file -+ * -+ * @param priv pointer uap_private -+ * @return N/A -+ */ -+void -+uap_proc_remove(uap_private * priv) -+{ -+ if (priv->proc_uap) { -+ if (priv->proc_entry) { -+ remove_proc_entry("info", priv->proc_entry); -+ remove_proc_entry("hwstatus", priv->proc_entry); -+ } -+ remove_proc_entry(priv->uap_dev.netdev->name, priv->proc_uap); -+ atomic_dec(&priv->proc_uap->count); -+ if (atomic_read(&(priv->proc_uap->count)) == 0) -+ remove_proc_entry("uap", PROC_DIR); -+ } -+} -+ -+/** -+ * @brief convert string to number -+ * -+ * @param s pointer to numbered string -+ * @return converted number from string s -+ */ -+int -+string_to_number(char *s) -+{ -+ int r = 0; -+ int base = 0; -+ int pn = 1; -+ -+ if (strncmp(s, "-", 1) == 0) { -+ pn = -1; -+ s++; -+ } -+ if ((strncmp(s, "0x", 2) == 0) || (strncmp(s, "0X", 2) == 0)) { -+ base = 16; -+ s += 2; -+ } else -+ base = 10; -+ -+ for (s = s; *s != 0; s++) { -+ if ((*s >= '0') && (*s <= '9')) -+ r = (r * base) + (*s - '0'); -+ else if ((*s >= 'A') && (*s <= 'F')) -+ r = (r * base) + (*s - 'A' + 10); -+ else if ((*s >= 'a') && (*s <= 'f')) -+ r = (r * base) + (*s - 'a' + 10); -+ else -+ break; -+ } -+ -+ return (r * pn); -+} -+ -+#endif -diff -Naupr linux-2.6.37/drivers/net/wireless/libertas_uap/uap_sdio_mmc.c linux-2.6.37-new/drivers/net/wireless/libertas_uap/uap_sdio_mmc.c ---- linux-2.6.37/drivers/net/wireless/libertas_uap/uap_sdio_mmc.c 1969-12-31 17:00:00.000000000 -0700 -+++ linux-2.6.37-new/drivers/net/wireless/libertas_uap/uap_sdio_mmc.c 2011-01-08 06:01:04.055834709 -0700 -@@ -0,0 +1,1428 @@ -+/** @file uap_sdio_mmc.c -+ * @brief This file contains SDIO IF (interface) module -+ * related functions. -+ * -+ * Copyright (C) 2007-2009, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available along with the File in the gpl.txt file or by writing to -+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ * -+ */ -+/**************************************************** -+Change log: -+****************************************************/ -+ -+#include "uap_sdio_mmc.h" -+ -+#include -+ -+/** define SDIO block size */ -+/* We support up to 480-byte block size due to FW buffer limitation. */ -+#define SD_BLOCK_SIZE 256 -+ -+/** define allocated buffer size */ -+#define ALLOC_BUF_SIZE (((MAX(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, \ -+ MRVDRV_SIZE_OF_CMD_BUFFER) + INTF_HEADER_LEN \ -+ + SD_BLOCK_SIZE - 1) / SD_BLOCK_SIZE) * SD_BLOCK_SIZE) -+ -+/** Max retry number of CMD53 write */ -+#define MAX_WRITE_IOMEM_RETRY 2 -+ -+/******************************************************** -+ Local Variables -+********************************************************/ -+ -+/** SDIO Rx unit */ -+static u8 sdio_rx_unit = 0; -+ -+/**Interrupt status */ -+static u8 sd_ireg = 0; -+/******************************************************** -+ Global Variables -+********************************************************/ -+extern u8 *helper_name; -+extern u8 *fw_name; -+/** Default helper name */ -+#define DEFAULT_HELPER_NAME "mrvl/helper_sd.bin" -+/** Default firmware name */ -+#define DEFAULT_FW_NAME "mrvl/sd8688_ap.bin" -+ -+/******************************************************** -+ Local Functions -+********************************************************/ -+/** -+ * @brief This function reads the IO register. -+ * -+ * @param priv A pointer to uap_private structure -+ * @param reg register to be read -+ * @param dat A pointer to variable that keeps returned value -+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE -+ */ -+static int -+sbi_read_ioreg(uap_private * priv, u32 reg, u8 * dat) -+{ -+ struct sdio_mmc_card *card; -+ int ret = UAP_STATUS_FAILURE; -+ -+ ENTER(); -+ -+ card = priv->uap_dev.card; -+ if (!card || !card->func) { -+ PRINTM(ERROR, "sbi_read_ioreg(): card or function is NULL!\n"); -+ goto done; -+ } -+ -+ *dat = sdio_readb(card->func, reg, &ret); -+ if (ret) { -+ PRINTM(ERROR, "sbi_read_ioreg(): sdio_readb failed! ret=%d\n", ret); -+ goto done; -+ } -+ -+ PRINTM(INFO, "sbi_read_ioreg() priv=%p func=%d reg=%#x dat=%#x\n", priv, -+ card->func->num, reg, *dat); -+ -+ done: -+ LEAVE(); -+ return ret; -+} -+ -+/** -+ * @brief This function writes the IO register. -+ * -+ * @param priv A pointer to uap_private structure -+ * @param reg register to be written -+ * @param dat the value to be written -+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE -+ */ -+static int -+sbi_write_ioreg(uap_private * priv, u32 reg, u8 dat) -+{ -+ struct sdio_mmc_card *card; -+ int ret = UAP_STATUS_FAILURE; -+ -+ ENTER(); -+ -+ card = priv->uap_dev.card; -+ if (!card || !card->func) { -+ PRINTM(ERROR, "sbi_write_ioreg(): card or function is NULL!\n"); -+ goto done; -+ } -+ -+ PRINTM(INFO, "sbi_write_ioreg() priv=%p func=%d reg=%#x dat=%#x\n", priv, -+ card->func->num, reg, dat); -+ -+ sdio_writeb(card->func, dat, reg, &ret); -+ if (ret) { -+ PRINTM(ERROR, "sbi_write_ioreg(): sdio_readb failed! ret=%d\n", ret); -+ goto done; -+ } -+ -+ done: -+ LEAVE(); -+ return ret; -+} -+ -+/** -+ * @brief This function get rx_unit value -+ * -+ * @param priv A pointer to uap_private structure -+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE -+ */ -+static int -+sd_get_rx_unit(uap_private * priv) -+{ -+ int ret = UAP_STATUS_SUCCESS; -+ u8 reg; -+ -+ ENTER(); -+ -+ ret = sbi_read_ioreg(priv, CARD_RX_UNIT_REG, ®); -+ if (ret == UAP_STATUS_SUCCESS) -+ sdio_rx_unit = reg; -+ -+ LEAVE(); -+ return ret; -+} -+ -+/** -+ * @brief This function reads rx length -+ * -+ * @param priv A pointer to uap_private structure -+ * @param dat A pointer to keep returned data -+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE -+ */ -+static int -+sd_read_rx_len(uap_private * priv, u16 * dat) -+{ -+ int ret = UAP_STATUS_SUCCESS; -+ u8 reg; -+ -+ ENTER(); -+ -+ ret = sbi_read_ioreg(priv, CARD_RX_LEN_REG, ®); -+ if (ret == UAP_STATUS_SUCCESS) -+ *dat = (u16) reg << sdio_rx_unit; -+ -+ LEAVE(); -+ return ret; -+} -+ -+/** -+ * @brief This function reads fw status registers -+ * -+ * @param priv A pointer to uap_private structure -+ * @param dat A pointer to keep returned data -+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE -+ */ -+static int -+sd_read_firmware_status(uap_private * priv, u16 * dat) -+{ -+ int ret = UAP_STATUS_SUCCESS; -+ u8 fws0; -+ u8 fws1; -+ -+ ENTER(); -+ -+ ret = sbi_read_ioreg(priv, CARD_FW_STATUS0_REG, &fws0); -+ if (ret < 0) { -+ LEAVE(); -+ return UAP_STATUS_FAILURE; -+ } -+ -+ ret = sbi_read_ioreg(priv, CARD_FW_STATUS1_REG, &fws1); -+ if (ret < 0) { -+ LEAVE(); -+ return UAP_STATUS_FAILURE; -+ } -+ -+ *dat = (((u16) fws1) << 8) | fws0; -+ -+ LEAVE(); -+ return UAP_STATUS_SUCCESS; -+} -+ -+/** -+ * @brief This function polls the card status register. -+ * -+ * @param priv A pointer to uap_private structure -+ * @param bits the bit mask -+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE -+ */ -+static int -+mv_sdio_poll_card_status(uap_private * priv, u8 bits) -+{ -+ int tries; -+ u8 cs; -+ -+ ENTER(); -+ -+ for (tries = 0; tries < MAX_POLL_TRIES; tries++) { -+ if (sbi_read_ioreg(priv, CARD_STATUS_REG, &cs) < 0) -+ break; -+ else if ((cs & bits) == bits) { -+ LEAVE(); -+ return UAP_STATUS_SUCCESS; -+ } -+ udelay(10); -+ } -+ -+ PRINTM(WARN, "mv_sdio_poll_card_status failed, tries = %d\n", tries); -+ -+ LEAVE(); -+ return UAP_STATUS_FAILURE; -+} -+ -+/** -+ * @brief This function set the sdio bus width. -+ * -+ * @param priv A pointer to uap_private structure -+ * @param mode 1--1 bit mode, 4--4 bit mode -+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE -+ */ -+#if 0 -+static int -+sdio_set_bus_width(uap_private * priv, u8 mode) -+{ -+ ENTER(); -+ LEAVE(); -+ return UAP_STATUS_SUCCESS; -+} -+#endif -+ -+/** -+ * @brief This function reads data from the card. -+ * -+ * @param priv A pointer to uap_private structure -+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE -+ */ -+static int -+sd_card_to_host(uap_private * priv) -+{ -+ int ret = UAP_STATUS_SUCCESS; -+ u16 buf_len = 0; -+ int buf_block_len; -+ int blksz; -+ struct sk_buff *skb = NULL; -+ u16 type; -+ u8 *payload = NULL; -+ struct sdio_mmc_card *card = priv->uap_dev.card; -+ -+ ENTER(); -+ -+ if (!card || !card->func) { -+ PRINTM(ERROR, "card or function is NULL!\n"); -+ ret = UAP_STATUS_FAILURE; -+ goto exit; -+ } -+ -+ /* Read the length of data to be transferred */ -+ ret = sd_read_rx_len(priv, &buf_len); -+ if (ret < 0) { -+ PRINTM(ERROR, "card_to_host, read scratch reg failed\n"); -+ ret = UAP_STATUS_FAILURE; -+ goto exit; -+ } -+ -+ /* Allocate buffer */ -+ blksz = SD_BLOCK_SIZE; -+ buf_block_len = (buf_len + blksz - 1) / blksz; -+ if (buf_len <= INTF_HEADER_LEN || (buf_block_len * blksz) > ALLOC_BUF_SIZE) { -+ PRINTM(ERROR, "card_to_host, invalid packet length: %d\n", buf_len); -+ ret = UAP_STATUS_FAILURE; -+ goto exit; -+ } -+#ifdef PXA3XX_DMA_ALIGN -+ skb = dev_alloc_skb(buf_block_len * blksz + PXA3XX_DMA_ALIGNMENT); -+#else -+ skb = dev_alloc_skb(buf_block_len * blksz); -+#endif -+ if (skb == NULL) { -+ PRINTM(WARN, "No free skb\n"); -+ goto exit; -+ } -+#ifdef PXA3XX_DMA_ALIGN -+ if ((u32) skb->data & (PXA3XX_DMA_ALIGNMENT - 1)) { -+ skb_put(skb, (u32) skb->data & (PXA3XX_DMA_ALIGNMENT - 1)); -+ skb_pull(skb, (u32) skb->data & (PXA3XX_DMA_ALIGNMENT - 1)); -+ } -+#endif /* PXA3XX_DMA_ALIGN */ -+ -+ payload = skb->tail; -+ ret = sdio_readsb(card->func, payload, priv->uap_dev.ioport, -+ buf_block_len * blksz); -+ if (ret < 0) { -+ PRINTM(ERROR, "card_to_host, read iomem failed: %d\n", ret); -+ ret = UAP_STATUS_FAILURE; -+ goto exit; -+ } -+ HEXDUMP("SDIO Blk Rd", payload, blksz * buf_block_len); -+ /* -+ * This is SDIO specific header -+ * u16 length, -+ * u16 type (MV_TYPE_DAT = 0, MV_TYPE_CMD = 1, MV_TYPE_EVENT = 3) -+ */ -+ buf_len = uap_le16_to_cpu(*(u16 *) & payload[0]); -+ type = uap_le16_to_cpu(*(u16 *) & payload[2]); -+ switch (type) { -+ case MV_TYPE_EVENT: -+ skb_put(skb, buf_len); -+ skb_pull(skb, INTF_HEADER_LEN); -+ uap_process_event(priv, skb->data, skb->len); -+ kfree_skb(skb); -+ skb = NULL; -+ break; -+ case MV_TYPE_CMD: -+ skb_put(skb, buf_len); -+ skb_pull(skb, INTF_HEADER_LEN); -+ priv->adapter->cmd_pending = FALSE; -+ if (priv->adapter->cmd_wait_option == -+ HostCmd_OPTION_WAITFORRSP_SLEEPCONFIRM) { -+ priv->adapter->cmd_wait_option = FALSE; -+ uap_process_sleep_confirm_resp(priv, skb->data, skb->len); -+ } else if (priv->adapter->cmd_wait_option) { -+ memcpy(priv->adapter->CmdBuf, skb->data, skb->len); -+ priv->adapter->CmdSize = skb->len; -+ priv->adapter->cmd_wait_option = FALSE; -+ priv->adapter->CmdWaitQWoken = TRUE; -+ wake_up_interruptible(&priv->adapter->cmdwait_q); -+ } -+ kfree_skb(skb); -+ skb = NULL; -+ break; -+ case MV_TYPE_DAT: -+ skb_put(skb, buf_len); -+ skb_pull(skb, INTF_HEADER_LEN); -+ uap_process_rx_packet(priv, skb); -+ break; -+ default: -+ priv->stats.rx_errors++; -+ priv->stats.rx_dropped++; -+ /* Driver specified event and command resp should be handle here */ -+ PRINTM(INFO, "Unknown PKT type:%d\n", type); -+ kfree_skb(skb); -+ skb = NULL; -+ break; -+ } -+ exit: -+ if (ret) { -+ if (skb) -+ kfree_skb(skb); -+ } -+ -+ LEAVE(); -+ return ret; -+} -+ -+/** -+ * @brief This function enables the host interrupts mask -+ * -+ * @param priv A pointer to uap_private structure -+ * @param mask the interrupt mask -+ * @return UAP_STATUS_SUCCESS -+ */ -+static int -+enable_host_int_mask(uap_private * priv, u8 mask) -+{ -+ int ret = UAP_STATUS_SUCCESS; -+ -+ ENTER(); -+ -+ /* Simply write the mask to the register */ -+ ret = sbi_write_ioreg(priv, HOST_INT_MASK_REG, mask); -+ -+ if (ret) { -+ PRINTM(WARN, "Unable to enable the host interrupt!\n"); -+ ret = UAP_STATUS_FAILURE; -+ } -+ -+ LEAVE(); -+ return ret; -+} -+ -+/** @brief This function disables the host interrupts mask. -+ * -+ * @param priv A pointer to uap_private structure -+ * @param mask the interrupt mask -+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE -+ */ -+static int -+disable_host_int_mask(uap_private * priv, u8 mask) -+{ -+ int ret = UAP_STATUS_SUCCESS; -+ u8 host_int_mask; -+ -+ ENTER(); -+ -+ /* Read back the host_int_mask register */ -+ ret = sbi_read_ioreg(priv, HOST_INT_MASK_REG, &host_int_mask); -+ if (ret) { -+ ret = UAP_STATUS_FAILURE; -+ goto done; -+ } -+ -+ /* Update with the mask and write back to the register */ -+ host_int_mask &= ~mask; -+ ret = sbi_write_ioreg(priv, HOST_INT_MASK_REG, host_int_mask); -+ if (ret < 0) { -+ PRINTM(WARN, "Unable to diable the host interrupt!\n"); -+ ret = UAP_STATUS_FAILURE; -+ goto done; -+ } -+ -+ done: -+ LEAVE(); -+ return ret; -+} -+ -+/******************************************************** -+ Global Functions -+********************************************************/ -+ -+/** -+ * @brief This function handles the interrupt. -+ * -+ * @param func A pointer to sdio_func structure. -+ * @return n/a -+ */ -+static void -+sbi_interrupt(struct sdio_func *func) -+{ -+ struct sdio_mmc_card *card; -+ uap_private *priv; -+ u8 ireg = 0; -+ int ret = UAP_STATUS_SUCCESS; -+ -+ ENTER(); -+ -+ card = sdio_get_drvdata(func); -+ if (!card || !card->priv) { -+ PRINTM(MSG, "%s: sbi_interrupt(%p) card or priv is NULL, card=%p\n", -+ __FUNCTION__, func, card); -+ LEAVE(); -+ return; -+ } -+ priv = card->priv; -+#ifdef FW_WAKEUP_TIME -+ if ((priv->adapter->wt_pwrup_sending != 0L) && -+ (priv->adapter->wt_int == 0L)) -+ priv->adapter->wt_int = get_utimeofday(); -+#endif -+ -+ ireg = sdio_readb(card->func, HOST_INTSTATUS_REG, &ret); -+ if (ret) { -+ PRINTM(WARN, "sdio_read_ioreg: read int status register failed\n"); -+ goto done; -+ } -+ if (ireg != 0) { -+ /* -+ * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS -+ * Clear the interrupt status register and re-enable the interrupt -+ */ -+ PRINTM(INFO, "sdio_ireg = 0x%x\n", ireg); -+ sdio_writeb(card->func, -+ ~(ireg) & (DN_LD_HOST_INT_STATUS | UP_LD_HOST_INT_STATUS), -+ HOST_INTSTATUS_REG, &ret); -+ if (ret) { -+ PRINTM(WARN, -+ "sdio_write_ioreg: clear int status register failed\n"); -+ goto done; -+ } -+ } -+ OS_INT_DISABLE; -+ sd_ireg |= ireg; -+ OS_INT_RESTORE; -+ -+ uap_interrupt(priv); -+ done: -+ LEAVE(); -+} -+ -+/** -+ * @brief This function probe the card -+ * -+ * @param func A pointer to sdio_func structure -+ * @param id A pointer to structure sd_device_id -+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE -+ */ -+static int -+uap_probe(struct sdio_func *func, const struct sdio_device_id *id) -+{ -+ int ret = UAP_STATUS_FAILURE; -+ struct sdio_mmc_card *card = NULL; -+ -+ ENTER(); -+ -+ PRINTM(MSG, "%s: vendor=0x%4.04X device=0x%4.04X class=%d function=%d\n", -+ __FUNCTION__, func->vendor, func->device, func->class, func->num); -+ -+ card = kzalloc(sizeof(struct sdio_mmc_card), GFP_KERNEL); -+ if (!card) { -+ ret = -ENOMEM; -+ goto done; -+ } -+ -+ card->func = func; -+ -+ if (!uap_add_card(card)) { -+ PRINTM(ERROR, "%s: uap_add_callback failed\n", __FUNCTION__); -+ kfree(card); -+ ret = UAP_STATUS_FAILURE; -+ goto done; -+ } -+ -+ ret = UAP_STATUS_SUCCESS; -+ -+ done: -+ LEAVE(); -+ return ret; -+} -+ -+/** -+ * @brief This function removes the card -+ * -+ * @param func A pointer to sdio_func structure -+ * @return N/A -+ */ -+static void -+uap_remove(struct sdio_func *func) -+{ -+ struct sdio_mmc_card *card; -+ -+ ENTER(); -+ -+ if (func) { -+ card = sdio_get_drvdata(func); -+ if (card) { -+ uap_remove_card(card); -+ kfree(card); -+ } -+ } -+ -+ LEAVE(); -+} -+ -+#ifdef CONFIG_PM -+/** -+ * @brief This function handles client driver suspend -+ * -+ * @param func A pointer to sdio_func structure -+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE -+ */ -+int -+uap_suspend(struct sdio_func *func) -+{ -+ ENTER(); -+ LEAVE(); -+ return 0; -+} -+ -+/** -+ * @brief This function handles client driver resume -+ * -+ * @param func A pointer to sdio_func structure -+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE -+ */ -+int -+uap_resume(struct sdio_func *func) -+{ -+ ENTER(); -+ LEAVE(); -+ return 0; -+} -+#endif -+ -+/** Device ID for SD8688 */ -+#define SD_DEVICE_ID_8688_UAP 0x9104 -+/** UAP IDs */ -+static const struct sdio_device_id uap_ids[] = { -+ {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SD_DEVICE_ID_8688_UAP)}, -+ {}, -+}; -+ -+MODULE_DEVICE_TABLE(sdio, uap_ids); -+ -+static struct sdio_driver uap_sdio = { -+ .name = "uap_sdio", -+ .id_table = uap_ids, -+ .probe = uap_probe, -+ .remove = uap_remove, -+#ifdef CONFIG_PM -+/* .suspend = uap_suspend, */ -+/* .resume = uap_resume, */ -+#endif -+ -+}; -+ -+/** -+ * @brief This function registers the IF module in bus driver. -+ * -+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE -+ */ -+int __init -+sbi_register() -+{ -+ int ret = UAP_STATUS_SUCCESS; -+ -+ ENTER(); -+ -+ /* SDIO Driver Registration */ -+ if (sdio_register_driver(&uap_sdio) != 0) { -+ PRINTM(FATAL, "SDIO Driver Registration Failed \n"); -+ ret = UAP_STATUS_FAILURE; -+ } -+ -+ LEAVE(); -+ return ret; -+} -+ -+/** -+ * @brief This function de-registers the IF module in bus driver. -+ * -+ * @return n/a -+ */ -+void __exit -+sbi_unregister(void) -+{ -+ ENTER(); -+ -+ /* SDIO Driver Unregistration */ -+ sdio_unregister_driver(&uap_sdio); -+ -+ LEAVE(); -+} -+ -+/** -+ * @brief This function checks the interrupt status and handle it accordingly. -+ * -+ * @param priv A pointer to uap_private structure -+ * @param ireg A pointer to variable that keeps returned value -+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE -+ */ -+int -+sbi_get_int_status(uap_private * priv, u8 * ireg) -+{ -+ int ret = UAP_STATUS_SUCCESS; -+ u8 sdio_ireg = 0; -+ struct sdio_mmc_card *card = priv->uap_dev.card; -+ -+ ENTER(); -+ -+ *ireg = 0; -+ OS_INT_DISABLE; -+ sdio_ireg = sd_ireg; -+ sd_ireg = 0; -+ OS_INT_RESTORE; -+ -+ sdio_claim_host(card->func); -+ -+ if (sdio_ireg & DN_LD_HOST_INT_STATUS) { /* tx_done INT */ -+ if (!priv->uap_dev.cmd_sent) { /* tx_done already received */ -+ PRINTM(INFO, -+ "warning: tx_done already received: tx_dnld_rdy=0x%x int status=0x%x\n", -+ priv->uap_dev.cmd_sent, sdio_ireg); -+ } else { -+ priv->uap_dev.cmd_sent = FALSE; -+ priv->uap_dev.data_sent = FALSE; -+ if ( (priv->uap_dev.netdev->reg_state == NETREG_REGISTERED) && (skb_queue_len(&priv->adapter->tx_queue) < TX_LOW_WATERMARK)) { -+ os_start_queue(priv); -+ } -+ } -+ } -+ if (sdio_ireg & UP_LD_HOST_INT_STATUS) { -+ sd_card_to_host(priv); -+ } -+ -+ *ireg = sdio_ireg; -+ ret = UAP_STATUS_SUCCESS; -+ sdio_release_host(card->func); -+ -+ LEAVE(); -+ return ret; -+} -+ -+/** -+ * @brief This function disables the host interrupts. -+ * -+ * @param priv A pointer to uap_private structure -+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE -+ */ -+int -+sbi_disable_host_int(uap_private * priv) -+{ -+ struct sdio_mmc_card *card = priv->uap_dev.card; -+ int ret; -+ -+ ENTER(); -+ -+ sdio_claim_host(card->func); -+ ret = disable_host_int_mask(priv, HIM_DISABLE); -+ sdio_release_host(card->func); -+ -+ LEAVE(); -+ return ret; -+} -+ -+/** -+ * @brief This function enables the host interrupts. -+ * -+ * @param priv A pointer to uap_private structure -+ * @return UAP_STATUS_SUCCESS -+ */ -+int -+sbi_enable_host_int(uap_private * priv) -+{ -+ struct sdio_mmc_card *card = priv->uap_dev.card; -+ int ret; -+ -+ ENTER(); -+ -+ sdio_claim_host(card->func); -+ ret = enable_host_int_mask(priv, HIM_ENABLE); -+ sdio_release_host(card->func); -+ -+ LEAVE(); -+ return ret; -+} -+ -+/** -+ * @brief This function de-registers the device. -+ * -+ * @param priv A pointer to uap_private structure -+ * @return UAP_STATUS_SUCCESS -+ */ -+int -+sbi_unregister_dev(uap_private * priv) -+{ -+ struct sdio_mmc_card *card = priv->uap_dev.card; -+ -+ ENTER(); -+ -+ if (!card || !card->func) { -+ PRINTM(ERROR, "Error: card or function is NULL!\n"); -+ goto done; -+ } -+ -+ sdio_claim_host(card->func); -+ sdio_release_irq(card->func); -+ sdio_disable_func(card->func); -+ sdio_release_host(card->func); -+ -+ sdio_set_drvdata(card->func, NULL); -+ -+ done: -+ LEAVE(); -+ return UAP_STATUS_SUCCESS; -+} -+ -+/** -+ * @brief This function registers the device. -+ * -+ * @param priv A pointer to uap_private structure -+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE -+ */ -+int -+sbi_register_dev(uap_private * priv) -+{ -+ int ret = UAP_STATUS_FAILURE; -+ u8 reg; -+ struct sdio_mmc_card *card = priv->uap_dev.card; -+ struct sdio_func *func; -+ -+ ENTER(); -+ -+ if (!card || !card->func) { -+ PRINTM(ERROR, "Error: card or function is NULL!\n"); -+ goto done; -+ } -+ -+ func = card->func; -+ -+ /* Initialize the private structure */ -+ priv->uap_dev.ioport = 0; -+ -+ sdio_claim_host(func); -+ -+ ret = sdio_enable_func(func); -+ if (ret) { -+ PRINTM(FATAL, "sdio_enable_func() failed: ret=%d\n", ret); -+ goto release_host; -+ } -+ -+ ret = sdio_claim_irq(func, sbi_interrupt); -+ if (ret) { -+ PRINTM(FATAL, "sdio_claim_irq failed: ret=%d\n", ret); -+ goto disable_func; -+ } -+ -+ /* Read the IO port */ -+ ret = sbi_read_ioreg(priv, IO_PORT_0_REG, ®); -+ if (ret) -+ goto release_irq; -+ else -+ priv->uap_dev.ioport |= reg; -+ -+ ret = sbi_read_ioreg(priv, IO_PORT_1_REG, ®); -+ if (ret) -+ goto release_irq; -+ else -+ priv->uap_dev.ioport |= (reg << 8); -+ -+ ret = sbi_read_ioreg(priv, IO_PORT_2_REG, ®); -+ if (ret) -+ goto release_irq; -+ else -+ priv->uap_dev.ioport |= (reg << 16); -+ -+ PRINTM(INFO, "SDIO FUNC #%d IO port: 0x%x\n", func->num, -+ priv->uap_dev.ioport); -+ -+ ret = sdio_set_block_size(card->func, SD_BLOCK_SIZE); -+ if (ret) { -+ PRINTM(ERROR, "%s: cannot set SDIO block size\n", __FUNCTION__); -+ ret = UAP_STATUS_FAILURE; -+ goto release_irq; -+ } -+ priv->hotplug_device = &func->dev; -+ -+ if (helper_name == NULL) { -+ helper_name = DEFAULT_HELPER_NAME; -+ } -+ if (fw_name == NULL) { -+ fw_name = DEFAULT_FW_NAME; -+ } -+ sdio_release_host(func); -+ -+ sdio_set_drvdata(func, card); -+ -+ ret = UAP_STATUS_SUCCESS; -+ goto done; -+ -+ release_irq: -+ sdio_release_irq(func); -+ disable_func: -+ sdio_disable_func(func); -+ release_host: -+ sdio_release_host(func); -+ -+ done: -+ LEAVE(); -+ return ret; -+} -+ -+/** -+ * @brief This function sends data to the card. -+ * -+ * @param priv A pointer to uap_private structure -+ * @param payload A pointer to the data/cmd buffer -+ * @param nb the length of data/cmd -+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE -+ */ -+int -+sbi_host_to_card(uap_private * priv, u8 * payload, u16 nb) -+{ -+ struct sdio_mmc_card *card = priv->uap_dev.card; -+ int ret = UAP_STATUS_SUCCESS; -+ int buf_block_len; -+ int blksz; -+ int i = 0; -+ u8 *buf = NULL; -+#ifdef PXA3XX_DMA_ALIGN -+ void *tmpbuf = NULL; -+ int tmpbufsz; -+#endif -+ -+ ENTER(); -+ -+ if (!card || !card->func) { -+ PRINTM(ERROR, "card or function is NULL!\n"); -+ LEAVE(); -+ return UAP_STATUS_FAILURE; -+ } -+ buf = payload; -+#ifdef PXA3XX_DMA_ALIGN -+ if ((u32) payload & (PXA3XX_DMA_ALIGNMENT - 1)) { -+ tmpbufsz = ALIGN_SZ(nb, PXA3XX_DMA_ALIGNMENT); -+ tmpbuf = kmalloc(tmpbufsz, GFP_KERNEL); -+ memset(tmpbuf, 0, tmpbufsz); -+ /* Ensure 8-byte aligned CMD buffer */ -+ buf = (u8 *) ALIGN_ADDR(tmpbuf, PXA3XX_DMA_ALIGNMENT); -+ memcpy(buf, payload, nb); -+ } -+#endif -+ /* Allocate buffer and copy payload */ -+ blksz = SD_BLOCK_SIZE; -+ buf_block_len = (nb + blksz - 1) / blksz; -+ sdio_claim_host(card->func); -+#define MAX_WRITE_IOMEM_RETRY 2 -+ priv->uap_dev.cmd_sent = TRUE; -+ priv->uap_dev.data_sent = TRUE; -+ do { -+ /* Transfer data to card */ -+ ret = sdio_writesb(card->func, priv->uap_dev.ioport, buf, -+ buf_block_len * blksz); -+ if (ret < 0) { -+ i++; -+ PRINTM(ERROR, "host_to_card, write iomem (%d) failed: %d\n", i, -+ ret); -+ ret = UAP_STATUS_FAILURE; -+ if (i > MAX_WRITE_IOMEM_RETRY) -+ goto exit; -+ } else { -+ HEXDUMP("SDIO Blk Wr", payload, nb); -+ } -+ } while (ret == UAP_STATUS_FAILURE); -+ exit: -+ sdio_release_host(card->func); -+#ifdef PXA3XX_DMA_ALIGN -+ if (tmpbuf) -+ kfree(tmpbuf); -+#endif -+ if (ret == UAP_STATUS_FAILURE) { -+ priv->uap_dev.cmd_sent = FALSE; -+ priv->uap_dev.data_sent = FALSE; -+ } -+ LEAVE(); -+ return ret; -+} -+ -+/** -+ * @brief This function reads CIS information. -+ * -+ * @param priv A pointer to uap_private structure -+ * @param cisinfo A pointer to CIS information output buffer -+ * @param cislen A pointer to length of CIS info output buffer -+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE -+ */ -+#if 0 -+static int -+sbi_get_cis_info(uap_private * priv, void *cisinfo, int *cislen) -+{ -+#define CIS_PTR (0x8000) -+ struct sdio_mmc_card *card = priv->uap_dev.card; -+ unsigned int i, cis_ptr = CIS_PTR; -+ int ret = UAP_STATUS_FAILURE; -+ -+ ENTER(); -+ -+ if (!card || !card->func) { -+ PRINTM(ERROR, "sbi_get_cis_info(): card or function is NULL!\n"); -+ goto exit; -+ } -+#define MAX_SDIO_CIS_INFO_LEN (256) -+ if (!cisinfo || (*cislen < MAX_SDIO_CIS_INFO_LEN)) { -+ PRINTM(WARN, "ERROR! get_cis_info: insufficient buffer passed\n"); -+ goto exit; -+ } -+ -+ *cislen = MAX_SDIO_CIS_INFO_LEN; -+ -+ sdio_claim_host(card->func); -+ -+ PRINTM(INFO, "cis_ptr=%#x\n", cis_ptr); -+ -+ /* Read the Tuple Data */ -+ for (i = 0; i < *cislen; i++) { -+ ((unsigned char *) cisinfo)[i] = -+ sdio_readb(card->func, cis_ptr + i, &ret); -+ if (ret) { -+ PRINTM(WARN, "get_cis_info error: ret=%d\n", ret); -+ ret = UAP_STATUS_FAILURE; -+ goto done; -+ } -+ PRINTM(INFO, "cisinfo[%d]=%#x\n", i, ((unsigned char *) cisinfo)[i]); -+ } -+ -+ done: -+ sdio_release_host(card->func); -+ exit: -+ LEAVE(); -+ return ret; -+} -+#endif -+/** -+ * @brief This function downloads helper image to the card. -+ * -+ * @param priv A pointer to uap_private structure -+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE -+ */ -+int -+sbi_prog_helper(uap_private * priv) -+{ -+ struct sdio_mmc_card *card = priv->uap_dev.card; -+ u8 *helper = NULL; -+ int helperlen; -+ int ret = UAP_STATUS_SUCCESS; -+ void *tmphlprbuf = NULL; -+ int tmphlprbufsz; -+ u8 *hlprbuf; -+ int hlprblknow; -+ u32 tx_len; -+#ifdef FW_DOWNLOAD_SPEED -+ u32 tv1, tv2; -+#endif -+ -+ ENTER(); -+ -+ if (!card || !card->func) { -+ PRINTM(ERROR, "sbi_prog_helper(): card or function is NULL!\n"); -+ goto done; -+ } -+ -+ if (priv->fw_helper) { -+ helper = (u8 *) priv->fw_helper->data; -+ helperlen = priv->fw_helper->size; -+ } else { -+ PRINTM(MSG, "No helper image found! Terminating download.\n"); -+ LEAVE(); -+ return UAP_STATUS_FAILURE; -+ } -+ -+ PRINTM(INFO, "Downloading helper image (%d bytes), block size %d bytes\n", -+ helperlen, SD_BLOCK_SIZE); -+ -+#ifdef FW_DOWNLOAD_SPEED -+ tv1 = get_utimeofday(); -+#endif -+ -+#ifdef PXA3XX_DMA_ALIGN -+ tmphlprbufsz = ALIGN_SZ(UAP_UPLD_SIZE, PXA3XX_DMA_ALIGNMENT); -+#else /* !PXA3XX_DMA_ALIGN */ -+ tmphlprbufsz = UAP_UPLD_SIZE; -+#endif /* !PXA3XX_DMA_ALIGN */ -+ tmphlprbuf = kmalloc(tmphlprbufsz, GFP_KERNEL); -+ if (!tmphlprbuf) { -+ PRINTM(ERROR, -+ "Unable to allocate buffer for helper. Terminating download\n"); -+ ret = UAP_STATUS_FAILURE; -+ goto done; -+ } -+ memset(tmphlprbuf, 0, tmphlprbufsz); -+#ifdef PXA3XX_DMA_ALIGN -+ hlprbuf = (u8 *) ALIGN_ADDR(tmphlprbuf, PXA3XX_DMA_ALIGNMENT); -+#else /* !PXA3XX_DMA_ALIGN */ -+ hlprbuf = (u8 *) tmphlprbuf; -+#endif /* !PXA3XX_DMA_ALIGN */ -+ -+ sdio_claim_host(card->func); -+ -+ /* Perform helper data transfer */ -+ tx_len = (FIRMWARE_TRANSFER_NBLOCK * SD_BLOCK_SIZE) - INTF_HEADER_LEN; -+ hlprblknow = 0; -+ do { -+ /* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY bits */ -+ ret = mv_sdio_poll_card_status(priv, CARD_IO_READY | DN_LD_CARD_RDY); -+ if (ret < 0) { -+ PRINTM(FATAL, "Helper download poll status timeout @ %d\n", -+ hlprblknow); -+ goto done; -+ } -+ -+ /* More data? */ -+ if (hlprblknow >= helperlen) -+ break; -+ -+ /* Set blocksize to transfer - checking for last block */ -+ if (helperlen - hlprblknow < tx_len) -+ tx_len = helperlen - hlprblknow; -+ -+ /* Set length to the 4-byte header */ -+ *(u32 *) hlprbuf = uap_cpu_to_le32(tx_len); -+ -+ /* Copy payload to buffer */ -+ memcpy(&hlprbuf[INTF_HEADER_LEN], &helper[hlprblknow], tx_len); -+ -+ PRINTM(INFO, "."); -+ -+ /* Send data */ -+ ret = sdio_writesb(card->func, priv->uap_dev.ioport, -+ hlprbuf, FIRMWARE_TRANSFER_NBLOCK * SD_BLOCK_SIZE); -+ -+ if (ret < 0) { -+ PRINTM(FATAL, "IO error during helper download @ %d\n", hlprblknow); -+ goto done; -+ } -+ -+ hlprblknow += tx_len; -+ } while (TRUE); -+ -+#ifdef FW_DOWNLOAD_SPEED -+ tv2 = get_utimeofday(); -+ PRINTM(INFO, "helper: %ld.%03ld.%03ld ", tv1 / 1000000, -+ (tv1 % 1000000) / 1000, tv1 % 1000); -+ PRINTM(INFO, " -> %ld.%03ld.%03ld ", tv2 / 1000000, (tv2 % 1000000) / 1000, -+ tv2 % 1000); -+ tv2 -= tv1; -+ PRINTM(INFO, " == %ld.%03ld.%03ld\n", tv2 / 1000000, (tv2 % 1000000) / 1000, -+ tv2 % 1000); -+#endif -+ -+ /* Write last EOF data */ -+ PRINTM(INFO, "\nTransferring helper image EOF block\n"); -+ memset(hlprbuf, 0x0, SD_BLOCK_SIZE); -+ ret = sdio_writesb(card->func, priv->uap_dev.ioport, -+ hlprbuf, SD_BLOCK_SIZE); -+ -+ if (ret < 0) { -+ PRINTM(FATAL, "IO error in writing helper image EOF block\n"); -+ goto done; -+ } -+ -+ ret = UAP_STATUS_SUCCESS; -+ -+ done: -+ sdio_release_host(card->func); -+ if (tmphlprbuf) -+ kfree(tmphlprbuf); -+ -+ LEAVE(); -+ return ret; -+} -+ -+/** -+ * @brief This function downloads firmware image to the card. -+ * -+ * @param priv A pointer to uap_private structure -+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE -+ */ -+int -+sbi_prog_fw_w_helper(uap_private * priv) -+{ -+ struct sdio_mmc_card *card = priv->uap_dev.card; -+ u8 *firmware = NULL; -+ int firmwarelen; -+ u8 base0; -+ u8 base1; -+ int ret = UAP_STATUS_SUCCESS; -+ int offset; -+ void *tmpfwbuf = NULL; -+ int tmpfwbufsz; -+ u8 *fwbuf; -+ u16 len; -+ int txlen = 0; -+ int tx_blocks = 0; -+ int i = 0; -+ int tries = 0; -+#ifdef FW_DOWNLOAD_SPEED -+ u32 tv1, tv2; -+#endif -+ -+ ENTER(); -+ -+ if (!card || !card->func) { -+ PRINTM(ERROR, "sbi_prog_fw_w_helper(): card or function is NULL!\n"); -+ goto done; -+ } -+ -+ if (priv->firmware) { -+ firmware = (u8 *) priv->firmware->data; -+ firmwarelen = priv->firmware->size; -+ } else { -+ PRINTM(MSG, "No firmware image found! Terminating download.\n"); -+ LEAVE(); -+ return UAP_STATUS_FAILURE; -+ } -+ -+ PRINTM(INFO, "Downloading FW image (%d bytes)\n", firmwarelen); -+ -+#ifdef FW_DOWNLOAD_SPEED -+ tv1 = get_utimeofday(); -+#endif -+ -+#ifdef PXA3XX_DMA_ALIGN -+ tmpfwbufsz = ALIGN_SZ(UAP_UPLD_SIZE, PXA3XX_DMA_ALIGNMENT); -+#else /* PXA3XX_DMA_ALIGN */ -+ tmpfwbufsz = UAP_UPLD_SIZE; -+#endif /* PXA3XX_DMA_ALIGN */ -+ tmpfwbuf = kmalloc(tmpfwbufsz, GFP_KERNEL); -+ if (!tmpfwbuf) { -+ PRINTM(ERROR, -+ "Unable to allocate buffer for firmware. Terminating download.\n"); -+ ret = UAP_STATUS_FAILURE; -+ goto done; -+ } -+ memset(tmpfwbuf, 0, tmpfwbufsz); -+#ifdef PXA3XX_DMA_ALIGN -+ /* Ensure 8-byte aligned firmware buffer */ -+ fwbuf = (u8 *) ALIGN_ADDR(tmpfwbuf, PXA3XX_DMA_ALIGNMENT); -+#else /* PXA3XX_DMA_ALIGN */ -+ fwbuf = (u8 *) tmpfwbuf; -+#endif /* PXA3XX_DMA_ALIGN */ -+ -+ sdio_claim_host(card->func); -+ -+ /* Perform firmware data transfer */ -+ offset = 0; -+ do { -+ /* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY bits */ -+ ret = mv_sdio_poll_card_status(priv, CARD_IO_READY | DN_LD_CARD_RDY); -+ if (ret < 0) { -+ PRINTM(FATAL, "FW download with helper poll status timeout @ %d\n", -+ offset); -+ goto done; -+ } -+ -+ /* More data? */ -+ if (offset >= firmwarelen) -+ break; -+ -+ for (tries = 0; tries < MAX_POLL_TRIES; tries++) { -+ if ((ret = sbi_read_ioreg(priv, HOST_F1_RD_BASE_0, &base0)) < 0) { -+ PRINTM(WARN, "Dev BASE0 register read failed:" -+ " base0=0x%04X(%d). Terminating download.\n", base0, -+ base0); -+ ret = UAP_STATUS_FAILURE; -+ goto done; -+ } -+ if ((ret = sbi_read_ioreg(priv, HOST_F1_RD_BASE_1, &base1)) < 0) { -+ PRINTM(WARN, "Dev BASE1 register read failed:" -+ " base1=0x%04X(%d). Terminating download.\n", base1, -+ base1); -+ ret = UAP_STATUS_FAILURE; -+ goto done; -+ } -+ len = (((u16) base1) << 8) | base0; -+ -+ /* For SD8688 wait until the length is not 0, 1 or 2 before -+ downloading the first FW block, since BOOT code writes the -+ register to indicate the helper/FW download winner, the value -+ could be 1 or 2 (Func1 or Func2). */ -+ if ((len && offset) || (len > 2)) -+ break; -+ udelay(10); -+ } -+ -+ if (len == 0) -+ break; -+ else if (len > UAP_UPLD_SIZE) { -+ PRINTM(FATAL, "FW download failure @ %d, invalid length %d\n", -+ offset, len); -+ ret = UAP_STATUS_FAILURE; -+ goto done; -+ } -+ -+ txlen = len; -+ -+ if (len & BIT(0)) { -+ i++; -+ if (i > MAX_WRITE_IOMEM_RETRY) { -+ PRINTM(FATAL, -+ "FW download failure @ %d, over max retry count\n", -+ offset); -+ ret = UAP_STATUS_FAILURE; -+ goto done; -+ } -+ PRINTM(ERROR, "FW CRC error indicated by the helper:" -+ " len = 0x%04X, txlen = %d\n", len, txlen); -+ len &= ~BIT(0); -+ /* Setting this to 0 to resend from same offset */ -+ txlen = 0; -+ } else { -+ i = 0; -+ -+ /* Set blocksize to transfer - checking for last block */ -+ if (firmwarelen - offset < txlen) { -+ txlen = firmwarelen - offset; -+ } -+ PRINTM(INFO, "."); -+ -+ tx_blocks = (txlen + SD_BLOCK_SIZE - 1) / SD_BLOCK_SIZE; -+ -+ /* Copy payload to buffer */ -+ memcpy(fwbuf, &firmware[offset], txlen); -+ } -+ -+ /* Send data */ -+ ret = sdio_writesb(card->func, priv->uap_dev.ioport, -+ fwbuf, tx_blocks * SD_BLOCK_SIZE); -+ -+ if (ret < 0) { -+ PRINTM(ERROR, "FW download, write iomem (%d) failed @ %d\n", i, -+ offset); -+ if (sbi_write_ioreg(priv, CONFIGURATION_REG, 0x04) < 0) { -+ PRINTM(ERROR, "write ioreg failed (CFG)\n"); -+ } -+ } -+ -+ offset += txlen; -+ } while (TRUE); -+ -+ PRINTM(INFO, "\nFW download over, size %d bytes\n", offset); -+ -+ ret = UAP_STATUS_SUCCESS; -+ done: -+#ifdef FW_DOWNLOAD_SPEED -+ tv2 = get_utimeofday(); -+ PRINTM(INFO, "FW: %ld.%03ld.%03ld ", tv1 / 1000000, -+ (tv1 % 1000000) / 1000, tv1 % 1000); -+ PRINTM(INFO, " -> %ld.%03ld.%03ld ", tv2 / 1000000, -+ (tv2 % 1000000) / 1000, tv2 % 1000); -+ tv2 -= tv1; -+ PRINTM(INFO, " == %ld.%03ld.%03ld\n", tv2 / 1000000, -+ (tv2 % 1000000) / 1000, tv2 % 1000); -+#endif -+ sdio_release_host(card->func); -+ if (tmpfwbuf) -+ kfree(tmpfwbuf); -+ -+ LEAVE(); -+ return ret; -+} -+ -+/** -+ * @brief This function checks if the firmware is ready to accept -+ * command or not. -+ * -+ * @param priv A pointer to uap_private structure -+ * @param pollnum Poll number -+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE -+ */ -+int -+sbi_check_fw_status(uap_private * priv, int pollnum) -+{ -+ struct sdio_mmc_card *card = priv->uap_dev.card; -+ int ret = UAP_STATUS_SUCCESS; -+ u16 firmwarestat; -+ int tries; -+ -+ ENTER(); -+ -+ sdio_claim_host(card->func); -+ -+ /* Wait for firmware initialization event */ -+ for (tries = 0; tries < pollnum; tries++) { -+ if ((ret = sd_read_firmware_status(priv, &firmwarestat)) < 0) -+ continue; -+ if (firmwarestat == FIRMWARE_READY) { -+ ret = UAP_STATUS_SUCCESS; -+ break; -+ } else { -+ mdelay(10); -+ ret = UAP_STATUS_FAILURE; -+ } -+ } -+ -+ if (ret < 0) -+ goto done; -+ -+ ret = UAP_STATUS_SUCCESS; -+ sd_get_rx_unit(priv); -+ -+ done: -+ sdio_release_host(card->func); -+ -+ LEAVE(); -+ return ret; -+} -+ -+/** -+ * @brief This function set bus clock on/off -+ * -+ * @param priv A pointer to uap_private structure -+ * @param option TRUE--on , FALSE--off -+ * @return UAP_STATUS_SUCCESS -+ */ -+#if 0 -+static int -+sbi_set_bus_clock(uap_private * priv, u8 option) -+{ -+ ENTER(); -+ LEAVE(); -+ return UAP_STATUS_SUCCESS; -+} -+#endif -+ -+/** -+ * @brief This function wakeup firmware -+ * -+ * @param priv A pointer to uap_private structure -+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE -+ */ -+int -+sbi_wakeup_firmware(uap_private * priv) -+{ -+ struct sdio_mmc_card *card = priv->uap_dev.card; -+ int ret = UAP_STATUS_SUCCESS; -+ -+ ENTER(); -+ -+ if (!card || !card->func) { -+ PRINTM(ERROR, "card or function is NULL!\n"); -+ LEAVE(); -+ return UAP_STATUS_FAILURE; -+ } -+ sdio_claim_host(card->func); -+ sdio_writeb(card->func, HOST_POWER_UP, CONFIGURATION_REG, &ret); -+ sdio_release_host(card->func); -+ LEAVE(); -+ return ret; -+} -diff -Naupr linux-2.6.37/drivers/net/wireless/libertas_uap/uap_sdio_mmc.h linux-2.6.37-new/drivers/net/wireless/libertas_uap/uap_sdio_mmc.h ---- linux-2.6.37/drivers/net/wireless/libertas_uap/uap_sdio_mmc.h 1969-12-31 17:00:00.000000000 -0700 -+++ linux-2.6.37-new/drivers/net/wireless/libertas_uap/uap_sdio_mmc.h 2011-01-08 06:01:04.057834571 -0700 -@@ -0,0 +1,136 @@ -+/** @file uap_sdio_mmc.h -+ * @brief This file contains SDIO IF (interface) module -+ * related macros, enum, and structure. -+ * -+ * Copyright (C) 2007-2009, Marvell International Ltd. -+ * -+ * This software file (the "File") is distributed by Marvell International -+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 -+ * (the "License"). You may use, redistribute and/or modify this File in -+ * accordance with the terms and conditions of the License, a copy of which -+ * is available along with the File in the gpl.txt file or by writing to -+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. -+ * -+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about -+ * this warranty disclaimer. -+ * -+ */ -+/**************************************************** -+Change log: -+ 10/10/07: initial version -+****************************************************/ -+ -+#ifndef _UAP_SDIO_MMC_H -+#define _UAP_SDIO_MMC_H -+ -+#include -+#include -+#include -+#include -+ -+#include "uap_headers.h" -+ -+/** The number of times to try when waiting for downloaded firmware to -+ become active. (polling the scratch register). */ -+#define MAX_FIRMWARE_POLL_TRIES 100 -+ -+/** Firmware ready */ -+#define FIRMWARE_READY 0xfedc -+ -+/** Number of firmware blocks to transfer */ -+#define FIRMWARE_TRANSFER_NBLOCK 2 -+ -+/* Host Control Registers */ -+/** Host Control Registers : I/O port 0 */ -+#define IO_PORT_0_REG 0x00 -+/** Host Control Registers : I/O port 1 */ -+#define IO_PORT_1_REG 0x01 -+/** Host Control Registers : I/O port 2 */ -+#define IO_PORT_2_REG 0x02 -+ -+/** Host Control Registers : Configuration */ -+#define CONFIGURATION_REG 0x03 -+/** Host Control Registers : Host without Command 53 finish host */ -+#define HOST_WO_CMD53_FINISH_HOST (0x1U << 2) -+/** Host Control Registers : Host power up */ -+#define HOST_POWER_UP (0x1U << 1) -+/** Host Control Registers : Host power down */ -+#define HOST_POWER_DOWN (0x1U << 0) -+ -+/** Host Control Registers : Host interrupt mask */ -+#define HOST_INT_MASK_REG 0x04 -+/** Host Control Registers : Upload host interrupt mask */ -+#define UP_LD_HOST_INT_MASK (0x1U) -+/** Host Control Registers : Download host interrupt mask */ -+#define DN_LD_HOST_INT_MASK (0x2U) -+/** Enable Host interrupt mask */ -+#define HIM_ENABLE (UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK) -+/** Disable Host interrupt mask */ -+#define HIM_DISABLE 0xff -+ -+/** Host Control Registers : Host interrupt status */ -+#define HOST_INTSTATUS_REG 0x05 -+/** Host Control Registers : Upload host interrupt status */ -+#define UP_LD_HOST_INT_STATUS (0x1U) -+/** Host Control Registers : Download host interrupt status */ -+#define DN_LD_HOST_INT_STATUS (0x2U) -+ -+/** Host F1 read base 0 */ -+#define HOST_F1_RD_BASE_0 0x10 -+/** Host F1 read base 1 */ -+#define HOST_F1_RD_BASE_1 0x11 -+ -+/** Card Control Registers : Card status register */ -+#define CARD_STATUS_REG 0x20 -+/** Card Control Registers : Card I/O ready */ -+#define CARD_IO_READY (0x1U << 3) -+/** Card Control Registers : CIS card ready */ -+#define CIS_CARD_RDY (0x1U << 2) -+/** Card Control Registers : Upload card ready */ -+#define UP_LD_CARD_RDY (0x1U << 1) -+/** Card Control Registers : Download card ready */ -+#define DN_LD_CARD_RDY (0x1U << 0) -+ -+/** Card Control Registers : Card OCR 0 register */ -+#define CARD_OCR_0_REG 0x34 -+/** Card Control Registers : Card OCR 1 register */ -+#define CARD_OCR_1_REG 0x35 -+ -+/** Firmware status 0 register */ -+#define CARD_FW_STATUS0_REG 0x40 -+/** Firmware status 1 register */ -+#define CARD_FW_STATUS1_REG 0x41 -+/** Rx length register */ -+#define CARD_RX_LEN_REG 0x42 -+/** Rx unit register */ -+#define CARD_RX_UNIT_REG 0x43 -+ -+/** Chip Id Register 0 */ -+#define CARD_CHIP_ID_0_REG 0x801c -+/** Chip Id Register 1 */ -+#define CARD_CHIP_ID_1_REG 0x801d -+ -+#ifdef PXA3XX_DMA_ALIGN -+/** DMA alignment value for PXA3XX platforms */ -+#define PXA3XX_DMA_ALIGNMENT 8 -+/** Macros for Data Alignment : size */ -+#define ALIGN_SZ(p, a) \ -+ (((p) + ((a) - 1)) & ~((a) - 1)) -+ -+/** Macros for Data Alignment : address */ -+#define ALIGN_ADDR(p, a) \ -+ ((((u32)(p)) + (((u32)(a)) - 1)) & ~(((u32)(a)) - 1)) -+#endif /* PXA3XX_DMA_ALIGN */ -+ -+struct sdio_mmc_card -+{ -+ /** sdio_func structure pointer */ -+ struct sdio_func *func; -+ /** uap_private structure pointer */ -+ uap_private *priv; -+}; -+ -+#endif /* _UAP_SDIO_MMC_H */ diff --git a/with-linux-3.4/linux-3.0.4-LIBERTAS-WEXT_PRIV.patch b/with-linux-3.4/linux-3.0.4-LIBERTAS-WEXT_PRIV.patch deleted file mode 100644 index 2c91ef1..0000000 --- a/with-linux-3.4/linux-3.0.4-LIBERTAS-WEXT_PRIV.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- ./drivers/net/wireless/libertas/Kconfig.orig 2011-08-29 14:56:30.000000000 -0600 -+++ ./drivers/net/wireless/libertas/Kconfig 2011-09-13 20:37:23.660904556 -0600 -@@ -3,6 +3,7 @@ config LIBERTAS - depends on CFG80211 - select WIRELESS_EXT - select WEXT_SPY -+ select WEXT_PRIV - select LIB80211 - select FW_LOADER - ---help--- diff --git a/with-linux-3.4/mvsdio-1-2.6.30.patch b/with-linux-3.4/mvsdio-1-2.6.30.patch deleted file mode 100644 index 63f0156..0000000 --- a/with-linux-3.4/mvsdio-1-2.6.30.patch +++ /dev/null @@ -1,18 +0,0 @@ ---- ./drivers/mmc/host/mvsdio.c.orig 2009-06-09 21:05:27.000000000 -0600 -+++ ./drivers/mmc/host/mvsdio.c 2009-06-23 23:20:36.085662093 -0600 -@@ -21,6 +21,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -148,6 +149,7 @@ static void mvsd_request(struct mmc_host - - dev_dbg(host->dev, "cmd %d (hw state 0x%04x)\n", - cmd->opcode, mvsd_read(MVSD_HW_STATE)); -+ if (cmd->opcode == SD_SWITCH) mdelay(1); /* Voodoo */ - - cmdreg = MVSD_CMD_INDEX(cmd->opcode); - diff --git a/with-linux-3.4/mvsdio-2.patch b/with-linux-3.4/mvsdio-2.patch deleted file mode 100644 index 8d53f2a..0000000 --- a/with-linux-3.4/mvsdio-2.patch +++ /dev/null @@ -1,35 +0,0 @@ -From: Nicolas Pitre -Date: Tue, 28 Apr 2009 02:38:12 +0000 (-0400) -Subject: [MMC] give Sandisk/Kingston SDHC cards some slack before the SWITCH command -X-Git-Url: http://git.marvell.com/?p=orion.git;a=commitdiff_plain;h=3ea638523747f6d312f11f643a3175c1a4661eec;hp=c0c3df02efed0e5dea9aa4d8313e06e1f68f2cb4 - -[MMC] give Sandisk/Kingston SDHC cards some slack before the SWITCH command - -Without this delay, those cards simply won't work in high speed mode -as the SWITCH command does not succeeds. - -Signed-off-by: Nicolas Pitre -Tested-by: Martin Michlmayr ---- - -diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c -index cd81c39..ba4c7ab 100644 ---- a/drivers/mmc/core/sd.c -+++ b/drivers/mmc/core/sd.c -@@ -263,6 +263,15 @@ static int mmc_switch_hs(struct mmc_card *card) - return -ENOMEM; - } - -+ /* -+ * Some SDHC cards, notably those with a Sandisk SD controller -+ * (also found in Kingston products) need a bit of slack -+ * before successfully handling the SWITCH command. So far, -+ * cards identifying themselves as "SD04G" and "SD08G" are -+ * affected -+ */ -+ udelay(100); -+ - err = mmc_sd_switch(card, 1, 0, 1, status); - if (err) - goto out; - diff --git a/with-linux-3.4/mvsdio-3.patch b/with-linux-3.4/mvsdio-3.patch deleted file mode 100644 index 76e96ce..0000000 --- a/with-linux-3.4/mvsdio-3.patch +++ /dev/null @@ -1,13 +0,0 @@ -Index: linux-3.4/drivers/mmc/core/core.c -=================================================================== ---- linux-3.4.orig/drivers/mmc/core/core.c 2012-05-27 15:26:08.394167850 -0300 -+++ linux-3.4/drivers/mmc/core/core.c 2012-05-27 15:26:38.085113097 -0300 -@@ -536,7 +536,7 @@ - */ - limit_us = 3000000; - else -- limit_us = 100000; -+ limit_us = 200000; - - /* - * SDHC cards always use these fixed values. diff --git a/with-linux-3.4/phys-virt.diff b/with-linux-3.4/phys-virt.diff deleted file mode 100644 index fc3d43e..0000000 --- a/with-linux-3.4/phys-virt.diff +++ /dev/null @@ -1,14 +0,0 @@ -Index: linux-3.4/arch/arm/Kconfig -=================================================================== ---- linux-3.4.orig/arch/arm/Kconfig 2012-05-27 17:00:06.244112647 -0300 -+++ linux-3.4/arch/arm/Kconfig 2012-05-27 17:01:06.456038133 -0300 -@@ -235,8 +235,7 @@ - - config PHYS_OFFSET - hex "Physical address of main memory" if MMU -- depends on !ARM_PATCH_PHYS_VIRT && !NEED_MACH_MEMORY_H -- default DRAM_BASE if !MMU -+ default 0x0 - help - Please provide the physical address corresponding to the - location of main memory in your system. diff --git a/with-linux-3.4/series b/with-linux-3.4/series deleted file mode 100644 index c143ea1..0000000 --- a/with-linux-3.4/series +++ /dev/null @@ -1,8 +0,0 @@ -dreamplug-3.4.0.patch -mvsdio-1-2.6.30.patch -mvsdio-2.patch -mvsdio-3.patch -linux-3.0-SDIO-micro-AP.patch -0002-Driver-for-Marvell-Libertas-8688-SDIO-micro-AP-suppo-3.2.patch -linux-3.0.4-LIBERTAS-WEXT_PRIV.patch -phys-virt.diff -- cgit v1.2.3